aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh')
-rw-r--r--lib/ssh/AUTHORS11
-rw-r--r--lib/ssh/Makefile39
-rw-r--r--lib/ssh/doc/html/.gitignore0
-rw-r--r--lib/ssh/doc/man3/.gitignore0
-rw-r--r--lib/ssh/doc/pdf/.gitignore0
-rw-r--r--lib/ssh/doc/src/Makefile205
-rw-r--r--lib/ssh/doc/src/book.xml46
-rw-r--r--lib/ssh/doc/src/fascicules.xml15
-rw-r--r--lib/ssh/doc/src/make.dep19
-rw-r--r--lib/ssh/doc/src/notes.xml588
-rw-r--r--lib/ssh/doc/src/notes_history.xml737
-rw-r--r--lib/ssh/doc/src/part_notes.xml38
-rw-r--r--lib/ssh/doc/src/part_notes_history.xml36
-rw-r--r--lib/ssh/doc/src/ref_man.xml41
-rw-r--r--lib/ssh/doc/src/ssh.xml337
-rw-r--r--lib/ssh/doc/src/ssh_channel.xml520
-rw-r--r--lib/ssh/doc/src/ssh_connection.xml302
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml501
-rw-r--r--lib/ssh/doc/src/ssh_sftpd.xml94
-rw-r--r--lib/ssh/doc/src/user_guide.gifbin0 -> 1581 bytes
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps3315
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt1624
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps2557
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt1232
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps2853
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt1627
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps3511
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt1962
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt2130
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps3205
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt1624
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps1881
-rw-r--r--lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt896
-rw-r--r--lib/ssh/ebin/.gitignore0
-rw-r--r--lib/ssh/examples/Makefile76
-rw-r--r--lib/ssh/examples/ssh_sample_cli.erl353
-rw-r--r--lib/ssh/info2
-rw-r--r--lib/ssh/priv/.gitignore0
-rwxr-xr-xlib/ssh/src/DSS.asn120
-rw-r--r--lib/ssh/src/Makefile157
-rwxr-xr-xlib/ssh/src/PKCS-1.asn1116
-rw-r--r--lib/ssh/src/prebuild.skip2
-rw-r--r--lib/ssh/src/ssh.app.src48
-rw-r--r--lib/ssh/src/ssh.appup.src37
-rw-r--r--lib/ssh/src/ssh.erl339
-rw-r--r--lib/ssh/src/ssh.hrl180
-rw-r--r--lib/ssh/src/ssh_acceptor.erl115
-rw-r--r--lib/ssh/src/ssh_acceptor_sup.erl95
-rw-r--r--lib/ssh/src/ssh_app.erl34
-rw-r--r--lib/ssh/src/ssh_auth.erl423
-rw-r--r--lib/ssh/src/ssh_auth.hrl83
-rwxr-xr-xlib/ssh/src/ssh_bits.erl483
-rw-r--r--lib/ssh/src/ssh_channel.erl328
-rw-r--r--lib/ssh/src/ssh_channel_sup.erl54
-rw-r--r--lib/ssh/src/ssh_cli.erl500
-rwxr-xr-xlib/ssh/src/ssh_cm.erl237
-rwxr-xr-xlib/ssh/src/ssh_connect.hrl264
-rw-r--r--lib/ssh/src/ssh_connection.erl1366
-rw-r--r--lib/ssh/src/ssh_connection_controler.erl137
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl879
-rw-r--r--lib/ssh/src/ssh_connection_manager.erl760
-rwxr-xr-xlib/ssh/src/ssh_dsa.erl95
-rwxr-xr-xlib/ssh/src/ssh_file.erl530
-rwxr-xr-xlib/ssh/src/ssh_io.erl79
-rwxr-xr-xlib/ssh/src/ssh_math.erl131
-rw-r--r--lib/ssh/src/ssh_no_io.erl39
-rwxr-xr-xlib/ssh/src/ssh_rsa.erl299
-rwxr-xr-xlib/ssh/src/ssh_sftp.erl1148
-rw-r--r--lib/ssh/src/ssh_sftpd.erl932
-rw-r--r--lib/ssh/src/ssh_sftpd_file.erl83
-rw-r--r--lib/ssh/src/ssh_sftpd_file_api.erl47
-rw-r--r--lib/ssh/src/ssh_shell.erl178
-rw-r--r--lib/ssh/src/ssh_ssh.erl65
-rw-r--r--lib/ssh/src/ssh_sshd.erl48
-rw-r--r--lib/ssh/src/ssh_subsystem_sup.erl109
-rw-r--r--lib/ssh/src/ssh_sup.erl101
-rw-r--r--lib/ssh/src/ssh_system_sup.erl160
-rw-r--r--lib/ssh/src/ssh_transport.erl1161
-rw-r--r--lib/ssh/src/ssh_transport.hrl235
-rwxr-xr-xlib/ssh/src/ssh_userauth.hrl77
-rw-r--r--lib/ssh/src/ssh_userreg.erl127
-rw-r--r--lib/ssh/src/ssh_xfer.erl925
-rwxr-xr-xlib/ssh/src/ssh_xfer.hrl251
-rw-r--r--lib/ssh/src/sshc_sup.erl65
-rw-r--r--lib/ssh/src/sshd_sup.erl111
-rw-r--r--lib/ssh/subdirs.mk4
-rw-r--r--lib/ssh/vsn.mk73
87 files changed, 46107 insertions, 0 deletions
diff --git a/lib/ssh/AUTHORS b/lib/ssh/AUTHORS
new file mode 100644
index 0000000000..8b1db86657
--- /dev/null
+++ b/lib/ssh/AUTHORS
@@ -0,0 +1,11 @@
+Original Authors:
+
+Tony Rogvall - first version
+Ingela Anderton Andin - ssh-1.0
+
+Contributors:
+
+Magnus Tho�ng
+H�kan Mattsson
+Jakob Cederlund
+Ingela Anderton Andin
diff --git a/lib/ssh/Makefile b/lib/ssh/Makefile
new file mode 100644
index 0000000000..1ad69a9ca1
--- /dev/null
+++ b/lib/ssh/Makefile
@@ -0,0 +1,39 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+#
+# Macros
+#
+
+SUB_DIRECTORIES = src doc/src
+
+include vsn.mk
+VSN = $(SSH_VSN)
+
+SPECIAL_TARGETS =
+
+#
+# Default Subdir Targets
+#
+include $(ERL_TOP)/make/otp_subdir.mk
+
+
diff --git a/lib/ssh/doc/html/.gitignore b/lib/ssh/doc/html/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ssh/doc/html/.gitignore
diff --git a/lib/ssh/doc/man3/.gitignore b/lib/ssh/doc/man3/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ssh/doc/man3/.gitignore
diff --git a/lib/ssh/doc/pdf/.gitignore b/lib/ssh/doc/pdf/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ssh/doc/pdf/.gitignore
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
new file mode 100644
index 0000000000..d2907a39d7
--- /dev/null
+++ b/lib/ssh/doc/src/Makefile
@@ -0,0 +1,205 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(SSH_VSN)
+APPLICATION=ssh
+
+# ----------------------------------------------------
+# Include dependency
+# ----------------------------------------------------
+
+
+ifndef DOCSUPPORT
+include make.dep
+endif
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+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\
+ ssh_sftp.xml \
+ ssh_sftpd.xml \
+
+XML_PART_FILES = part_notes.xml part_notes_history.xml
+XML_CHAPTER_FILES = notes.xml notes_history.xml
+
+BOOK_FILES = book.xml
+
+# ----------------------------------------------------
+
+HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+
+INFO_FILE = ../../info
+EXTRA_FILES = \
+ $(DEFAULT_GIF_FILES) \
+ $(DEFAULT_HTML_FILES) \
+ $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
+
+# notes_history.html \
+
+
+MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
+
+
+ifdef DOCSUPPORT
+
+HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
+
+TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+
+else
+
+TEX_FILES_BOOK = \
+ $(BOOK_FILES:%.xml=%.tex)
+TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \
+ $(XML_APPLICATION_FILES:%.xml=%.tex)
+TEX_FILES_USERS_GUIDE = \
+ $(XML_CHAPTER_FILES:%.xml=%.tex)
+
+TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf
+TOP_PS_FILE = $(APPLICATION)-$(VSN).ps
+
+$(TOP_PDF_FILE): book.dvi ../../vsn.mk
+ $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@
+
+$(TOP_PS_FILE): book.dvi ../../vsn.mk
+ $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@
+
+endif
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+XML_FLAGS +=
+DVIPS_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+$(HTMLDIR)/%.gif: %.gif
+ $(INSTALL_DATA) $< $@
+
+ifdef DOCSUPPORT
+
+docs: pdf html man
+
+$(TOP_PDF_FILE): $(XML_FILES)
+
+pdf: $(TOP_PDF_FILE)
+
+html: $(HTML_REF_MAN_FILE)
+
+clean clean_docs:
+ rm -rf $(HTMLDIR)/*
+ rm -f $(MAN3DIR)/*
+ rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f errs core *~
+
+else
+
+ifeq ($(DOCTYPE),pdf)
+docs: pdf
+else
+ifeq ($(DOCTYPE),ps)
+docs: ps
+else
+docs: html man
+endif
+endif
+
+pdf: $(TOP_PDF_FILE)
+
+ps: $(TOP_PS_FILE)
+
+html: $(HTML_FILES)
+
+clean clean_docs clean_tex:
+ rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK)
+ rm -f $(HTML_FILES) $(MAN3_FILES)
+ rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE)
+ rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN)
+
+endif
+
+man: $(MAN3_FILES)
+
+
+debug opt:
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+ifdef DOCSUPPORT
+
+release_docs_spec: docs
+ $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
+ $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
+ $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DATA) $(HTMLDIR)/* \
+ $(RELSYSDIR)/doc/html
+ $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
+ $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+else
+
+ifeq ($(DOCTYPE),pdf)
+release_docs_spec: pdf
+ $(INSTALL_DIR) $(RELEASE_PATH)/pdf
+ $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf
+else
+ifeq ($(DOCTYPE),ps)
+release_docs_spec: ps
+ $(INSTALL_DIR) $(RELEASE_PATH)/ps
+ $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps
+else
+release_docs_spec: docs
+ $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DATA) $(EXTRA_FILES) $(HTML_FILES) \
+ $(RELSYSDIR)/doc/html
+ $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
+ $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
+endif
+endif
+
+endif
+
+release_spec:
diff --git a/lib/ssh/doc/src/book.xml b/lib/ssh/doc/src/book.xml
new file mode 100644
index 0000000000..0375c441af
--- /dev/null
+++ b/lib/ssh/doc/src/book.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE book SYSTEM "book.dtd">
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header titlestyle="normal">
+ <copyright>
+ <year>2005</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>SSH</title>
+ <prepared>OTP Team</prepared>
+ <docno></docno>
+ <date>2007-10-06</date>
+ <rev>%VSN%</rev>
+ <file>book.sgml</file>
+ </header>
+ <insidecover>
+ </insidecover>
+ <pagetext>SSH</pagetext>
+ <preamble>
+ <contents level="2"></contents>
+ </preamble>
+ <applications>
+ <xi:include href="ref_man.xml"/>
+ </applications>
+ <releasenotes>
+ <xi:include href="notes.xml"/>
+ </releasenotes>
+ <listofterms></listofterms>
+ <index></index>
+</book>
+
diff --git a/lib/ssh/doc/src/fascicules.xml b/lib/ssh/doc/src/fascicules.xml
new file mode 100644
index 0000000000..43090b4aed
--- /dev/null
+++ b/lib/ssh/doc/src/fascicules.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
+
+<fascicules>
+ <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
+ Reference Manual
+ </fascicule>
+ <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
+ Release Notes
+ </fascicule>
+ <fascicule file="" href="../../../../doc/print.html" entry="no">
+ Off-Print
+ </fascicule>
+</fascicules>
+
diff --git a/lib/ssh/doc/src/make.dep b/lib/ssh/doc/src/make.dep
new file mode 100644
index 0000000000..cfe2f9617b
--- /dev/null
+++ b/lib/ssh/doc/src/make.dep
@@ -0,0 +1,19 @@
+# ----------------------------------------------------
+# >>>> Do not edit this file <<<<
+# This file was automaticly generated by
+# /home/otp/bin/docdepend
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# TeX files that the DVI file depend on
+# ----------------------------------------------------
+
+book.dvi: book.tex ref_man.tex ssh.tex ssh_channel.tex \
+ ssh_connection.tex ssh_sftp.tex ssh_sftpd.tex
+
+# ----------------------------------------------------
+# Source inlined when transforming from source to LaTeX
+# ----------------------------------------------------
+
+book.tex: ref_man.xml
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
new file mode 100644
index 0000000000..54e0cf9059
--- /dev/null
+++ b/lib/ssh/doc/src/notes.xml
@@ -0,0 +1,588 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2004</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>SSH Release Notes</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev>%VSN%</rev>
+ <file>notes.xml</file>
+ </header>
+
+ <section><title>Ssh 1.1.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Now clear all processes when a connnection is terminated.</p>
+ <p>
+ Own Id: OTP-8121 Aux Id:</p>
+ </item>
+ <item>
+ <p>
+ In some rare cases the connection handler could enter an infinite loop.</p>
+ <p>
+ Own Id: OTP-8277 Aux Id: seq11428</p>
+ </item>
+ <item>
+ <p>
+ If an SFTP server did not respond with EOF, the function
+ ssh_sftp:list_dir/2/3 would enter an infinite loop.</p>
+ <p>
+ Own Id: OTP-8278 Aux Id: seq11450</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The documentation is now built with open source tools (xsltproc and fop)
+ that exists on most platforms. One visible change is that the frames are removed.</p>
+ <p>
+ Own Id: OTP-8201 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ ssh_sftp:start_channel did not handle all possible return
+ values from ssh_channel:start correctly.
+ </p>
+ <p>
+ Own Id: OTP-8176 Aux Id: </p>
+ </item>
+ <item>
+ <p>
+ SFTPD did not handle rename command (version 4) correctly.
+ </p>
+ <p>
+ Own Id: OTP-8175 Aux Id: seq11373</p>
+ </item>
+ <item>
+ <p>
+ If a connection manager already had been terminated it could cause a channel
+ to generate a crash report when it was about to stop.
+ </p>
+ <p>
+ Own Id: OTP-8174 Aux Id: seq11377</p>
+ </item>
+ <item>
+ <p>
+ Requests could result in badarg or badmatch EXIT messages in the connection
+ manager if the channel no longer existed.</p>
+ <p>
+ Own Id: OTP-8173 Aux Id: seq11379</p>
+ </item>
+ <item>
+ <p>
+ ssh_transport:unpack/3 could cause a badarg error.</p>
+ <p>
+ Own Id: OTP-8162 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The encryption algorithm aes128-cbc is now supported.
+ Requires that crypto-1.6.1 is available.</p>
+ <p>
+ Own Id: OTP-8110 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+
+ <section><title>Ssh 1.1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ ssh_sftp:start_channel/3 did not handle timout correctly.</p>
+ <p>
+ Own Id: OTP-8159 Aux Id: seq11386</p>
+ </item>
+ <item>
+ <p>
+ If a progress message was not recieved after invoking ssh:connect/3
+ the call could hang for ever. A timeout option has also been added.</p>
+ <p>
+ Own Id: OTP-8160 Aux Id: seq11386</p>
+ </item>
+ <item>
+ <p>
+ A comma has been missing in the ssh.appup file since SSH-1.0.2.</p>
+ <p>
+ Own Id: OTP-8161 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SSH sometimes caused a crash report at disconnect.</p>
+ <p>
+ Own Id: OTP-8071 Aux Id: seq11319</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The operation ssh_sftp:stop_channel/1 returned an
+ exception if the connection already had been closed.</p>
+ <p>
+ Own Id: OTP-7996 Aux Id: seq11281</p>
+ </item>
+ <item>
+ <p>
+ SSH did not handle if supervisor:start_child/2 returned
+ {error, already_present}.</p>
+ <p>
+ Own Id: OTP-8034 Aux Id: seq11307</p>
+ </item>
+ <item>
+ <p>
+ SSH no longer cause supervisor reports when a connection is
+ terminated in a controlled manner.</p>
+ <p>
+ Own Id: OTP-8035 Aux Id: seq11308</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Ssh confused local and remote channel id's, which in some
+ cases resulted in that messages were discarded.</p>
+ <p>
+ Own Id: OTP-7914 Aux Id: seq11234</p>
+ </item>
+ <item>
+ <p>
+ Ssh could not handle echo values other than 0 and 1.</p>
+ <p>
+ Own Id: OTP-7917 Aux Id: seq11238</p>
+ </item>
+ <item>
+ <p>
+ A crash occurred if a non-valid channel reference was received.</p>
+ <p>
+ Own Id: OTP-7918 Aux Id: seq11238</p>
+ </item>
+ <item>
+ <p>
+ Sftpd connections was not closed after receiving eof from a client.</p>
+ <p>
+ Own Id: OTP-7921 Aux Id: seq11222</p>
+ </item>
+ <item>
+ <p>
+ It was not possible to start a SFTP subsystem on certain platforms,
+ i.e. those who do not support symbolic links.</p>
+ <p>
+ Own Id: OTP-7930 Aux Id: </p>
+ </item>
+ <item>
+ <p>
+ In some cases the message {ssh_cm, ssh_connection_ref(), {closed, ssh_channel_id()}}
+ was not passed to the registered callback module.</p>
+ <p>
+ Own Id: OTP-7957 Aux Id: </p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ By using the sftpd option {max_files, Integer}, the message
+ size for READDIR commands can be reduced.</p>
+ <p>
+ Own Id: OTP-7919 Aux Id: seq11230</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The erlang ssh server has presented itself incorrectly,
+ using the special version ssh-1.99, although it never has
+ supported versions below 2.0. Since ssh-1.1 client
+ versions below 2.0 are correctly rejected instead of
+ letting the server crash later on. Alas the problem with
+ the presentation string was not discovered until after
+ ssh.1.1 was released. Now the server will present itself
+ as ssh-2.0.</p>
+ <p>
+ Own Id: OTP-7795</p>
+ </item>
+ <item>
+ <p>
+ An internal function call used an incorrect parameter, which
+ caused problem when the old listen API was used. This was
+ introduced in Ssh-1.1.</p>
+ <p>
+ Own Id: OTP-7920 Aux Id: seq11211</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Ssh timeouts will now behave as expected e.i. defaults to
+ infinity only the user of the ssh application can know of
+ a reasonable timeout value for their application.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-7807</p>
+ </item>
+ <item>
+ <p>
+ The implementation of timeouts added as a patch in
+ ssh-1.0.1 was slightly changed and is now documented.</p>
+ <p>
+ Own Id: OTP-7808</p>
+ </item>
+ <item>
+ <p>
+ To honor the multiplexing of channels over one ssh
+ connection concept ssh_sftp:connect/ [1,2,3] is
+ deprecated and replaced by ssh_sftp:start_channel/[1,2,3]
+ and ssh_sftp:stop/1 is deprecated and replaced by
+ ssh_sftp:stop_channel/1 and to stop the ssh connection
+ ssh:close/ 1 should be called.</p>
+ <p>
+ Own Id: OTP-7809</p>
+ </item>
+ <item>
+ <p>
+ Added the message {ssh_channel_up, ChannelId,
+ ConnectionManager} that shall be handled by the channel
+ callback handle_msg/2. This makes the function
+ handle_msg/2 a mandatory function for ssh channels
+ implementations which it was not in ssh-1.1.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-7828</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A flaw in the implementation of the supervision tree
+ caused the ssh daemon to close the connections to all
+ currently logged in users if one user logged out. Another
+ problem related to the supervision tree caused the closing
+ down of clients to leak processes e.i. all processes was
+ not shutdown correctly.</p>
+ <p>
+ Own Id: OTP-7676</p>
+ </item>
+ <item>
+ <p>
+ Tabs could cause ssh_cli to print things in a surprising
+ way.</p>
+ <p>
+ Own Id: OTP-7683 Aux Id: seq11102 </p>
+ </item>
+ <item>
+ <p>
+ [sftp, sftpd] - Added patch to make sftp timestamps more
+ correct, in the long run it would be nice to have better
+ support in file to be able to make it always behave
+ correctly now it will be correct 99 % of time instead of
+ almost never correct, at least on unix-based platforms.</p>
+ <p>
+ Own Id: OTP-7685 Aux Id: seq11082 </p>
+ </item>
+ <item>
+ <p>
+ [sftpd] - Added patch to further improve handling of
+ symbolic links in the sftp-server.</p>
+ <p>
+ Own Id: OTP-7766 Aux Id: seq11101 </p>
+ </item>
+ <item>
+ <p>
+ Ssh incorrectly sent the local id instead of the remote
+ id of a channel to the peer. For simpler cases these ids
+ often happen to have the same value. One case when they
+ do not is when the client sends an exec command two times
+ in a raw on the same ssh connection (different channels
+ of course as the channel will be closed when the exec
+ command has been evaluated) .</p>
+ <p>
+ Own Id: OTP-7767</p>
+ </item>
+ <item>
+ <p>
+ Packet data could be lost under high load due to the fact
+ that buffered data was sometimes wrongly discarded before
+ it had been sent.</p>
+ <p>
+ Own Id: OTP-7768</p>
+ </item>
+ <item>
+ <p>
+ Improved ipv6-handling as some assumptions about inet
+ functions where incorrect.</p>
+ <p>
+ Own Id: OTP-7770</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added new API function ssh:connection_info/2.</p>
+ <p>
+ Own Id: OTP-7456</p>
+ </item>
+ <item>
+ <p>
+ Now starts ssh channel processes later avoiding
+ synchronization problems between processes.</p>
+ <p>
+ Own Id: OTP-7516</p>
+ </item>
+ <item>
+ <p>
+ Ssh now rejects old versions of the ssh protocol for
+ security reasons. (Even if they where not correctly
+ rejected before the connection would probably have failed
+ anyway due to other reasons.)</p>
+ <p>
+ Own Id: OTP-7645 Aux Id: seq11094 </p>
+ </item>
+ <item>
+ <p>
+ New API module ssh_channel has been added. This is a
+ behaviour to facilitate the implementation of ssh clients
+ and plug in subsystems to the ssh daemon. Note that this
+ slightly changes the options to the API function
+ ssh:daemon/[1,2,3] deprecating all no longer documented
+ options. Note that the new API enforces the "logical way"
+ of using the old API e.i. making the subsystem process
+ part of the ssh applications supervisor tree, so missuses
+ of the old API are not compatible with the new API.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-7769</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ Public keys protected by a password are currently not
+ handled by the erlang ssh application.</p>
+ <p>
+ Own Id: OTP-6400 Aux Id: 10595 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ [sftpd] - Listing of symbolic link directories should now
+ work as expected.</p>
+ <p>
+ Own Id: OTP-7141 Aux Id: seq10856 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ [sftp] - When listing a directory with more than 100
+ files only the first 100 where listed. This has now been
+ fixed.</p>
+ <p>
+ Own Id: OTP-7318 Aux Id: seq10953 </p>
+ </item>
+ <item>
+ <p>
+ When restarting an ssh-system the expected return value
+ from ssh_system_sup:restart_acceptor/2 was incorrect,
+ this is no longer the case.</p>
+ <p>
+ Own Id: OTP-7564 Aux Id: seq11055 </p>
+ </item>
+ <item>
+ <p>
+ A few minor bugs where fixed in ssh_userreg.erl and
+ ssh_connection_manager and a a ssh_cli option was added
+ to restore backwards compatibility with the old ssh_cm -
+ API.</p>
+ <p>
+ Own Id: OTP-7565</p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in ipv6 support and added option to disable
+ ipv6 as a workaround for badly configured computers.</p>
+ <p>
+ Own Id: OTP-7566</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ [sftp] - Option added to set timeout value in sftp.</p>
+ <p>
+ Own Id: OTP-7305 Aux Id: seq10945 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 1.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed some special handling of prompts that made ssh
+ behave differently than openssh.</p>
+ <p>
+ Own Id: OTP-7485 Aux Id: seq11025 </p>
+ </item>
+ <item>
+ <p>
+ Bug in encoding of pty opts has been fixed.</p>
+ <p>
+ Own Id: OTP-7504</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The architecture of the ssh processes has been
+ reconstructed to fit in a supervision tree as to become a
+ real OTP application and benefit from this when starting
+ and stopping.</p>
+ <p>
+ Own Id: OTP-7356 Aux Id: seq10899 </p>
+ </item>
+ <item>
+ <p>
+ Support for pty option echo off added. Requires kernel
+ from R12B-4.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-7502 Aux Id: seq10959 </p>
+ </item>
+ <item>
+ <p>
+ The ssh API has been enhanced a lot of old API functions
+ has become deprecated.</p>
+ <p>
+ Own Id: OTP-7503</p>
+ </item>
+ </list>
+ </section>
+
+ <!-- p>For information about older versions see
+ <url href="part_notes_history_frame.html">release notes history</url>.</p -->
+ </section>
+</chapter>
+
diff --git a/lib/ssh/doc/src/notes_history.xml b/lib/ssh/doc/src/notes_history.xml
new file mode 100644
index 0000000000..bfebcd4bf4
--- /dev/null
+++ b/lib/ssh/doc/src/notes_history.xml
@@ -0,0 +1,737 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2009</year>
+ <year>2009</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>SSH Release Notes History</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>notes_history.xml</file>
+ </header>
+
+ <section><title>Ssh 0.9.9.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Updated asn1 file due to change in the asn1 compiler.
+ This has no semantical effect on the ssh application.</p>
+ <p>
+ Own Id: OTP-7246</p>
+ </item>
+ <item>
+ <p>
+ Allows for the option {fd, FD} in listen and connect
+ calls. The option is passed on to gen_tcp:listen and
+ gen_tcp:connect</p>
+ <p>
+ Own Id: OTP-7247</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+ <section><title>Ssh 0.9.9.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Putty version 0.60 sends ignore messages, which hanged
+ the OTP ssh server.</p>
+ <p>
+ Own Id: OTP-7076</p>
+ </item>
+ <item>
+ <p>
+ ssh_cm hanged when connection was closed during
+ handshake. (Triggered by putty 0.60 client.)</p>
+ <p>
+ Own Id: OTP-7089</p>
+ </item>
+ <item>
+ <p>
+ Fixed crash in server when receiving an empty ignore-msg.
+ (From the putty 0.60 client.)</p>
+ <p>
+ Own Id: OTP-7135</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Now uses the base 64 encode/decode function in stdlib.</p>
+ <p>
+ Own Id: OTP-6486</p>
+ </item>
+ <item>
+ <p>
+ Removed runtime dependency on asn1.</p>
+ <p>
+ Own Id: OTP-6570</p>
+ </item>
+ <item>
+ <p>
+ Documentation update of ssh.</p>
+ <p>
+ Own Id: OTP-7063 Aux Id: seq10789 </p>
+ </item>
+ <item>
+ <p>
+ Same listener is used for both sshd and sftpd. Previously
+ the sftpd server had to be run on a separate port, now
+ the sshd listener will start an sftpd server when an sftp
+ client connects.</p>
+ <p>
+ Own Id: OTP-7090 Aux Id: seq10675 </p>
+ </item>
+ <item>
+ <p>
+ Kebord-interactive support, according to rfc 4256, has
+ been added to the ssh client. Also the option
+ <c>quiet_mode</c> has been added so that unwanted banners
+ may be suppressed.</p>
+ <p>
+ Own Id: OTP-7106 Aux Id: seq10841 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Ssh 0.9.9.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ [sftpd] - Root parameter now behaves as expected,
+ instead of making sftpd malfunction.</p>
+ <p>
+ Own Id: OTP-7057 Aux Id: seq10830 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section><title>Ssh 0.9.9.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The sftp-server could crash if a "ls" was done on the
+ client, and a file was removed while ssh_sftpd:list_dir
+ was reading the directory, an error code from
+ read_file_info wasn't handled properly. This fix makes ls
+ return an error code instead.</p>
+ <p>
+ Own Id: OTP-6854 Aux Id: seq10740 </p>
+ </item>
+ <item>
+ <p>
+ Fixed bugs in prompting in ssl_cli. Prompts like \003>
+ were written as \300>. Also, newlines and returns was
+ removed.</p>
+ <p>
+ Own Id: OTP-6917 Aux Id: seq10773 </p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ [sftpd] - New option "root" to set the root of the
+ sftp-server and the callback module for file handling now
+ has a state parameter.</p>
+ <p>
+ Own Id: OTP-7075 Aux Id: seq10675 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.9.2</title>
+ <section>
+ <title>Better error-handling in ssh_sshd:listen</title>
+ <list type="bulleted">
+ <item>
+ <p>The caller was hanged when listening with ssh_sshd:listen
+ (or ssh_sftpd:listen) on a port and IP already in use.
+ Now an error is returned instead.</p>
+ <p>Own Id: OTP-6727</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Fix in ssh_sftpd</title>
+ <list type="bulleted">
+ <item>
+ <p>Cd ../.. didn't work when connecting to a ssh_sftpd server.</p>
+ <p>Own Id: OTP-6727</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.9.1</title>
+
+ <section>
+ <title>Minor Makefile changes</title>
+ <list type="bulleted">
+ <item>
+ <p>Removed use of <c><![CDATA[erl_flags]]></c> from Makefile.</p>
+ <p>Own Id: OTP-6689</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.9</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>A race condition that could make the server crash if a
+ client sent a SSH_MSG_USERAUTH_REQUEST packet immediately
+ after its SSH_MSG_SERVICE_REQUEST, is removed.</p>
+ <p>Own Id: OTP-6379 Aux Id: seq10523 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.8</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Corrected minor bugs and removed dead code found by
+ dialyzer.</p>
+ <p>Own Id: OTP-6524</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.7</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>[sftp] - The function ssh_sftp:make_symlink/3 was not
+ fully implemented.</p>
+ <p>Own Id: OTP-6446</p>
+ </item>
+ <item>
+ <p>[ssh] - An internal value was, due to a bug, always set
+ to undefined even when it was not, this could lead to
+ connections being wrongly refused.</p>
+ <p>Own Id: OTP-6450</p>
+ </item>
+ <item>
+ <p>A pattern matching was missing "/binary" resulting in
+ that the internal function ssh_xfer:decode_acl/2 did not
+ work as expected.</p>
+ <p>Own Id: OTP-6458</p>
+ </item>
+ <item>
+ <p>[sftp] - read_link/2 did not return the documented value</p>
+ <p>Own Id: OTP-6471</p>
+ </item>
+ <item>
+ <p>Removed debugg printouts from ssh_cli.erl</p>
+ <p>Own Id: OTP-6483</p>
+ </item>
+ <item>
+ <p>[sftp, ssh] - The connection timeout was overridden by an
+ internal gen_server default timeout.</p>
+ <p>Own Id: OTP-6488 Aux Id: seq10569 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.6</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Removed debug printout from production code.</p>
+ <p>Own Id: OTP-6348 Aux Id: seq10510 </p>
+ </item>
+ <item>
+ <p>[sftpd] - When the sftp client ends the session the
+ server will now behave correctly and not leave the client
+ hanging.</p>
+ <p>Own Id: OTP-6349 Aux Id: seq10510 </p>
+ </item>
+ <item>
+ <p>[sftpd] - No longer used files were not closed until the
+ session was ended.</p>
+ <p>Own Id: OTP-6350 Aux Id: seq10514 </p>
+ </item>
+ <item>
+ <p>[sftpd] - File rename requests sent by sftp version 3
+ clients were not handled.</p>
+ <p>Own Id: OTP-6352 Aux Id: seq10513 </p>
+ </item>
+ <item>
+ <p>[sftpd] - Request that did not fit into one ssh message
+ were not handled.</p>
+ <p>Own Id: OTP-6353 Aux Id: seq10515 </p>
+ </item>
+ <item>
+ <p>Removed error logging of auth method none, as this is not
+ an error but rather a feature, that is used to get
+ initial information from the server.</p>
+ <p>Own Id: OTP-6414</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>[sftpd] - Added new option to specify a callback module
+ for the sftpd-server file handling. The default callback
+ module uses file and filelib.</p>
+ <p>Own Id: OTP-6356 Aux Id: seq10519 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.5</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>The data window in SSH wasn't resized in the ssh_cli
+ receive data, this made the ssh_cli-server hang if more
+ than 64K data was received at one time. The option
+ tcp_nodelay was added, for nodelay in tcp connections.</p>
+ <p>Own Id: OTP-6231</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.4</title>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Unnecessary explicit start of crypto application
+ in ssh application. This has been removed. The
+ app-file specifies that ssh depends on the crypto app.
+ This is enough. See also the
+ <seealso marker="ssh">ssh</seealso> module.</p>
+ <p>Also changed some error reports to info reports.</p>
+ <p>Own Id: OTP-6183</p>
+ <p>Aux Id: Seq 10383</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.3</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Added way for cli to get peer name</p>
+ <p>Own Id: OTP-6138</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.2</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Added some options to listen</p>
+ <p>Own Id: OTP-6070</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.1</title>
+ <section><title>Ssh 0.9.9.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ [sftpd] - Root parameter now behaves as expected,
+ instead of making sftpd malfunction.</p>
+ <p>
+ Own Id: OTP-7057 Aux Id: seq10830 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section><title>Ssh 0.9.9.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The sftp-server could crash if a "ls" was done on the
+ client, and a file was removed while ssh_sftpd:list_dir
+ was reading the directory, an error code from
+ read_file_info wasn't handled properly. This fix makes ls
+ return an error code instead.</p>
+ <p>
+ Own Id: OTP-6854 Aux Id: seq10740 </p>
+ </item>
+ <item>
+ <p>
+ Fixed bugs in prompting in ssl_cli. Prompts like \003>
+ were written as \300>. Also, newlines and returns was
+ removed.</p>
+ <p>
+ Own Id: OTP-6917 Aux Id: seq10773 </p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ [sftpd] - New option "root" to set the root of the
+ sftp-server and the callback module for file handling now
+ has a state parameter.</p>
+ <p>
+ Own Id: OTP-7075 Aux Id: seq10675 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.9.2</title>
+ <section>
+ <title>Better error-handling in ssh_sshd:listen</title>
+ <list type="bulleted">
+ <item>
+ <p>The caller was hanged when listening with ssh_sshd:listen
+ (or ssh_sftpd:listen) on a port and IP already in use.
+ Now an error is returned instead.</p>
+ <p>Own Id: OTP-6727</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Fix in ssh_sftpd</title>
+ <list type="bulleted">
+ <item>
+ <p>Cd ../.. didn't work when connecting to a ssh_sftpd server.</p>
+ <p>Own Id: OTP-6727</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.9.1</title>
+
+ <section>
+ <title>Minor Makefile changes</title>
+ <list type="bulleted">
+ <item>
+ <p>Removed use of <c><![CDATA[erl_flags]]></c> from Makefile.</p>
+ <p>Own Id: OTP-6689</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.9</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>A race condition that could make the server crash if a
+ client sent a SSH_MSG_USERAUTH_REQUEST packet immediately
+ after its SSH_MSG_SERVICE_REQUEST, is removed.</p>
+ <p>Own Id: OTP-6379 Aux Id: seq10523 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.8</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Corrected minor bugs and removed dead code found by
+ dialyzer.</p>
+ <p>Own Id: OTP-6524</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.7</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>[sftp] - The function ssh_sftp:make_symlink/3 was not
+ fully implemented.</p>
+ <p>Own Id: OTP-6446</p>
+ </item>
+ <item>
+ <p>[ssh] - An internal value was, due to a bug, always set
+ to undefined even when it was not, this could lead to
+ connections being wrongly refused.</p>
+ <p>Own Id: OTP-6450</p>
+ </item>
+ <item>
+ <p>A pattern matching was missing "/binary" resulting in
+ that the internal function ssh_xfer:decode_acl/2 did not
+ work as expected.</p>
+ <p>Own Id: OTP-6458</p>
+ </item>
+ <item>
+ <p>[sftp] - read_link/2 did not return the documented value</p>
+ <p>Own Id: OTP-6471</p>
+ </item>
+ <item>
+ <p>Removed debugg printouts from ssh_cli.erl</p>
+ <p>Own Id: OTP-6483</p>
+ </item>
+ <item>
+ <p>[sftp, ssh] - The connection timeout was overridden by an
+ internal gen_server default timeout.</p>
+ <p>Own Id: OTP-6488 Aux Id: seq10569 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.6</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Removed debug printout from production code.</p>
+ <p>Own Id: OTP-6348 Aux Id: seq10510 </p>
+ </item>
+ <item>
+ <p>[sftpd] - When the sftp client ends the session the
+ server will now behave correctly and not leave the client
+ hanging.</p>
+ <p>Own Id: OTP-6349 Aux Id: seq10510 </p>
+ </item>
+ <item>
+ <p>[sftpd] - No longer used files were not closed until the
+ session was ended.</p>
+ <p>Own Id: OTP-6350 Aux Id: seq10514 </p>
+ </item>
+ <item>
+ <p>[sftpd] - File rename requests sent by sftp version 3
+ clients were not handled.</p>
+ <p>Own Id: OTP-6352 Aux Id: seq10513 </p>
+ </item>
+ <item>
+ <p>[sftpd] - Request that did not fit into one ssh message
+ were not handled.</p>
+ <p>Own Id: OTP-6353 Aux Id: seq10515 </p>
+ </item>
+ <item>
+ <p>Removed error logging of auth method none, as this is not
+ an error but rather a feature, that is used to get
+ initial information from the server.</p>
+ <p>Own Id: OTP-6414</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>[sftpd] - Added new option to specify a callback module
+ for the sftpd-server file handling. The default callback
+ module uses file and filelib.</p>
+ <p>Own Id: OTP-6356 Aux Id: seq10519 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Ssh 0.9.5</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>The data window in SSH wasn't resized in the ssh_cli
+ receive data, this made the ssh_cli-server hang if more
+ than 64K data was received at one time. The option
+ tcp_nodelay was added, for nodelay in tcp connections.</p>
+ <p>Own Id: OTP-6231</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.4</title>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Unnecessary explicit start of crypto application
+ in ssh application. This has been removed. The
+ app-file specifies that ssh depends on the crypto app.
+ This is enough. See also the
+ <seealso marker="ssh">ssh</seealso> module.</p>
+ <p>Also changed some error reports to info reports.</p>
+ <p>Own Id: OTP-6183</p>
+ <p>Aux Id: Seq 10383</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.3</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Added way for cli to get peer name</p>
+ <p>Own Id: OTP-6138</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.2</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Added some options to listen</p>
+ <p>Own Id: OTP-6070</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9.1</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Fixes in ssh_sftp, changes of timeout handling,
+ expand_fun moved to io:setopts</p>
+ <p>Own Id: OTP-5877 Aux Id: OTP-5781 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>SSH 0.9</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>The previously undocumented and UNSUPPORTED <c><![CDATA[ssh]]></c>
+ application has been updated and documented. This release
+ of the <c><![CDATA[ssh]]></c> application is still considered to be a
+ beta release and (if necessary) there could still be
+ changes in its API before it reaches 1.0.</p>
+ <p>Also, more cryptographic algorithms have been added to
+ the <c><![CDATA[crypto]]></c> application.</p>
+ <p>*** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>Own Id: OTP-5631</p>
+ </item>
+ </list>
+ </section>
+ </section>
+ </section>
+
+</chapter>
+
+
diff --git a/lib/ssh/doc/src/part_notes.xml b/lib/ssh/doc/src/part_notes.xml
new file mode 100644
index 0000000000..f87efffe5c
--- /dev/null
+++ b/lib/ssh/doc/src/part_notes.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2004</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>SSH Release Notes</title>
+ <prepared>Jakob Cederlund</prepared>
+ <docno></docno>
+ <date></date>
+ <rev>%VSN%</rev>
+ <file>part_notes.sgml</file>
+ </header>
+ <description>
+ <p>This document describes the changes made to the SSH application.
+ </p>
+ <p>For information about older versions see
+ <url href="part_notes_history_frame.html">release notes history</url>.</p> </description>
+ <xi:include file="notes.xml"/>
+</part>
+
diff --git a/lib/ssh/doc/src/part_notes_history.xml b/lib/ssh/doc/src/part_notes_history.xml
new file mode 100644
index 0000000000..49f72fd3db
--- /dev/null
+++ b/lib/ssh/doc/src/part_notes_history.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part>
+ <header>
+ <copyright>
+ <year>2004</year>
+ <year>2007</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>Ssh</title>
+ <prepared>Ingela Anderton Andin</prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>part_notes.xml</file>
+ </header>
+ <include file="notes_history"></include>
+</part>
+
+
diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml
new file mode 100644
index 0000000000..c05c3051b0
--- /dev/null
+++ b/lib/ssh/doc/src/ref_man.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE application SYSTEM "application.dtd">
+
+<application xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2004</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>SSH Reference Manual</title>
+ <prepared>Jakob Cederlund</prepared>
+ <docno></docno>
+ <date>2007-10-06</date>
+ <rev>%VSN%</rev>
+ <file>application.sgml</file>
+ </header>
+ <description>
+ <p>The SSH application is an erlang implementation of the
+ secure shell protocol.</p>
+ </description>
+ <xi:include href="ssh.xml"/>
+ <xi:include href="ssh_channel.xml"/>
+ <xi:include href="ssh_connection.xml"/>
+ <xi:include href="ssh_sftp.xml"/>
+ <xi:include href="ssh_sftpd.xml"/>
+</application>
+
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
new file mode 100644
index 0000000000..aca5c9cdc4
--- /dev/null
+++ b/lib/ssh/doc/src/ssh.xml
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2004</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>ssh</title>
+ <prepared>Ingela Anderton Andin</prepared>
+ <responsible>H&aring;kan Mattsson</responsible>
+ <docno></docno>
+ <approved>H&aring;kan Mattsson</approved>
+ <checked></checked>
+ <date>2007-10-06</date>
+ <rev>PA1</rev>
+ </header>
+ <module>ssh</module>
+ <modulesummary>Main API of the SSH application</modulesummary>
+ <description>
+ <p>Interface module for the SSH application</p>
+ </description>
+
+
+ <section>
+ <title>COMMON DATA TYPES </title>
+ <p>Type definitions that are used more than once in
+ this module:</p>
+ <p><c>boolean() = true | false </c></p>
+ <p><c>string() = list of ASCII characters</c></p>
+ <p><c>ssh_daemon_ref() - opaque to the user
+ returned by ssh:daemon/[1,2,3]</c></p>
+ <p><c>ssh_connection_ref() - opaque to the user
+ returned by ssh:connect/3</c></p>
+ <p><c>ip_address() - {N1,N2,N3,N4} % IPv4 |
+ {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6</c></p>
+ <p><c>subsystem_spec() = {subsystem_name(), {channel_callback(), channel_init_args()}} </c></p>
+ <p><c>subsystem_name() = string() </c></p>
+ <p><c>channel_callback() = atom() - Name of the erlang module
+ implementing the subsystem using the ssh_channel behavior see</c>
+ <seealso marker="ssh_channel">ssh_channel(3)</seealso></p>
+ <p><c>channel_init_args() = list()</c></p>
+ </section>
+
+ <funcs>
+
+ <func>
+ <name>close(ConnectionRef) -> ok </name>
+ <fsummary>Closes a ssh connection</fsummary>
+ <type>
+ <v>ConnectionRef = ssh_connection_ref()</v>
+ </type>
+ <desc><p>Closes a ssh connection.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>connect(Host, Port, Options) -> </name>
+ <name>connect(Host, Port, Options, Timeout) -> {ok, ssh_connection_ref()}
+ | {error, Reason}</name>
+ <fsummary>Connect to an ssh server.</fsummary>
+ <type>
+ <v>Host = string()</v>
+ <v>Port = integer()</v>
+ <d>The default is <c><![CDATA[22]]></c>, the registered port for SSH.</d>
+ <v>Options = [{Option, Value}]</v>
+ <v>Timeout = infinity | integer(milliseconds)</v>
+ </type>
+ <desc>
+ <p>Connects to an SSH server. No channel is started this is done
+ by calling ssh_connect:session_channel/2.</p>
+ <p>Options are:</p>
+ <taglist>
+ <tag><c><![CDATA[{user_dir, String}]]></c></tag>
+ <item>
+ <p>Sets the user directory e.i. the directory containing
+ ssh 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[{silently_accept_hosts, boolean()}]]></c></tag>
+ <item>
+ <p>When true hosts are added to the
+ file <c><![CDATA[known_hosts]]></c> without asking the user.
+ Defaults to false.
+ </p>
+ </item>
+ <tag><c><![CDATA[{user_interaction, boolean()}]]></c></tag>
+ <item>
+ <p>If false disables the client to connect to the server
+ if any user interaction is needed such as accepting that
+ the server will be added to the <c>known_hosts</c> file or
+ supplying a password. Defaults to true.
+ Even if user interaction is allowed it can be
+ suppressed by other options such as silently_accept_hosts and
+ password. Do note that it may not always be desirable to use
+ those options from a security point of view.</p>
+ </item>
+ <tag><c><![CDATA[{public_key_alg, ssh_rsa | ssh_dsa}]]></c></tag>
+ <item>
+ <p>Sets the preferred public key algorithm to use for user
+ authentication. If the the preferred algorithm fails of
+ some reason, the other algorithm is tried. The default is
+ to try <c><![CDATA[ssh_rsa]]></c> first.</p>
+ </item>
+ <tag><c><![CDATA[{connect_timeout, timeout()}]]></c></tag>
+ <item>
+ <p>Sets a timeout on the transport layer connection. Defaults to infinity.</p>
+ </item>
+ <tag><c><![CDATA[{user, String}]]></c></tag>
+ <item>
+ <p>Provide a user name. If this option is not given, ssh
+ 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>
+ <item>
+ <p>Provide a password for password authentication. If
+ this option is not given, the user will be asked for a
+ password if the password authentication method is
+ attempted.</p>
+ </item>
+ <tag><c><![CDATA[{user_auth, Fun/3}]]></c></tag>
+ <item>
+ <p>Provide a fun for password authentication. The fun
+ will be called as <c><![CDATA[fun(User, Password, Opts)]]></c> and
+ should return <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>.</p>
+ </item>
+ <tag><c><![CDATA[{key_cb, atom() = KeyCallbackModule}]]></c></tag>
+ <item>
+ <p>Provide a special call-back module for key handling.
+ The call-back module should be modeled after the
+ <c><![CDATA[ssh_file]]></c> module. The functions that must
+ be exported are:
+ <c><![CDATA[private_host_rsa_key/2]]></c>,
+ <c><![CDATA[private_host_dsa_key/2]]></c>,
+ <c><![CDATA[lookup_host_key/3]]></c> and
+ <c><![CDATA[add_host_key/3]]></c>. This is considered
+ somewhat experimental and will be better documented later on.</p>
+ </item>
+ <tag><c><![CDATA[{fd, file_descriptor()}]]></c></tag>
+ <item>
+ <p>Allow an existing file-descriptor to be used
+ (simply passed on to the transport protocol).</p></item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>connection_info(ConnectionRef, [Option]) ->[{Option, Value}] </name>
+ <fsummary> Retrieves information about a connection. </fsummary>
+ <type>
+ <v>Option = client_version | server_version | peer</v>
+ <v>Value = term() </v>
+ </type>
+ <desc>
+ <p> Retrieves information about a connection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>daemon(Port) -> </name>
+ <name>daemon(Port, Options) -> </name>
+ <name>daemon(HostAddress, Port, Options) -> ssh_daemon_ref()</name>
+ <fsummary>Starts a server listening for SSH connections
+ on the given port.</fsummary>
+ <type>
+ <v>Port = integer()</v>
+ <v>HostAddress = ip_address() | any</v>
+ <v>Options = [{Option, Value}]</v>
+ <v>Option = atom()</v>
+ <v>Value = term()</v>
+ </type>
+ <desc>
+ <p>Starts a server listening for SSH connections on the given port.</p>
+
+ <p>Options are:</p>
+ <taglist>
+ <tag><c><![CDATA[{subsystems, [subsystem_spec()]]]></c></tag>
+ <item>
+ Provides specifications for handling of subsystems. The
+ "sftp" subsystem-spec can be retrieved by calling
+ ssh_sftd:subsystem_spec/1. If the subsystems option in not present
+ the value of <c>[ssh_sftd:subsystem_spec([])]</c> will be used.
+ It is of course possible to set the option to the empty list
+ if you do not want the daemon to run any subsystems at all.
+ </item>
+ <tag><c><![CDATA[{shell, {Module, Function, Args} | fun(string() = User) - > pid() |
+ fun(string() = User, ip_address() = PeerAddr) -> pid()}]]></c></tag>
+ <item>
+ Defines the read-eval-print loop used when a shell is requested
+ by the client. Example use the
+ erlang shell: <c><![CDATA[{shell, start, []}]]></c> which is
+ the default behavior.
+ </item>
+ <tag><c><![CDATA[{ssh_cli,{channel_callback(), channel_init_args()}}]]></c></tag>
+ <item>
+ Provide your own cli implementation, e.i. a channel callback
+ module that implements a shell and command execution. Note
+ that you may customize the shell read-eval-print loop using the
+ option <c>shell</c> which is much less work than implementing
+ your own cli channel.
+ </item>
+ <tag><c><![CDATA[{system_dir, string()}]]></c></tag>
+ <item>
+ <p>Sets the system directory, containing the host files
+ that identifies the host for ssh. The default is
+ <c><![CDATA[/etc/ssh]]></c>, note that SSH normally
+ requires the host files there to be readable only by
+ root.</p>
+ </item>
+ <tag><c><![CDATA[{user_passwords, [{string() = User, string() = Password}]}]]></c></tag>
+ <item>
+ <p>Provide passwords for password authentication.They will
+ be used when someone tries to connect to the server and
+ public key user authentication fails. The option provides
+ a list of valid user names and the corresponding password.
+ </p>
+ </item>
+ <tag><c><![CDATA[{password, string()}]]></c></tag>
+ <item>
+ <p>Provide a global password that will authenticate any
+ user. From a security perspective this option makes
+ the server very vulnerable.</p>
+ </item>
+ <tag><c><![CDATA[{pwdfun, fun/2}]]></c></tag>
+ <item>
+ <p>Provide a function for password validation. This is called
+ with user and password as strings, and should return
+ <c><![CDATA[true]]></c> if the password is valid and
+ <c><![CDATA[false]]></c> otherwise.</p>
+ </item>
+ <tag><c><![CDATA[{fd, file_descriptor()}]]></c></tag>
+ <item>
+ <p>Allow an existing file-descriptor to be used
+ (simply passed on to the transport protocol).</p></item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>shell(Host) -> </name>
+ <name>shell(Host, Option) -> </name>
+ <name>shell(Host, Port, Option) -> _</name>
+ <fsummary> </fsummary>
+ <type>
+ <v> Host = string()</v>
+ <v> Port = integer()</v>
+ <v> Options - see ssh:connect/3</v>
+ </type>
+ <desc>
+ <p>Starts an interactive shell to an SSH server on the
+ given <c>Host</c>. The function waits for user input,
+ and will not return until the remote shell is ended (e.g. on
+ exit from the shell).
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>start() -> </name>
+ <name>start(Type) -> ok | {error, Reason}</name>
+ <fsummary>Starts the Ssh application. </fsummary>
+ <type>
+ <v>Type = permanent | transient | temporary</v>
+ <v>Reason = term() </v>
+ </type>
+ <desc>
+ <p>Starts the Ssh application. Default type
+ is temporary. See also
+ <seealso marker="kernel:application">application(3)</seealso>
+ Requires that the crypto application has been started.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>stop() -> ok </name>
+ <fsummary>Stops the Ssh application.</fsummary>
+ <desc>
+ <p>Stops the Ssh application. See also
+ <seealso marker="kernel:application">application(3)</seealso></p>
+ </desc>
+ </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>
+ <desc>
+ <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 up and running.</fsummary>
+ <type>
+ <v>DaemonRef = ssh_daemon_ref()</v>
+ <v>Address = ip_address()</v>
+ <v>Port = integer()</v>
+ </type>
+ <desc>
+ <p>Stops the listener, but leaves existing connections started
+ by the listener up and running.</p>
+ </desc>
+ </func>
+ </funcs>
+
+</erlref>
diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_channel.xml
new file mode 100644
index 0000000000..c2b7aa94a5
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_channel.xml
@@ -0,0 +1,520 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2009</year>
+ <year>2009</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>ssh_channel</title>
+ <prepared>Ingela Anderton Andin</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>ssh_channel</module>
+ <modulesummary>Generic Ssh Channel Behavior
+ </modulesummary>
+ <description>
+ <p>Ssh services are implemented as channels that are multiplexed
+ over an ssh connection and communicates via the ssh connection
+ protocol. This module provides a callback API that takes care of
+ generic channel aspects such as flow control and close messages
+ and lets the callback functions take care of the service specific
+ parts.
+ </p>
+ </description>
+
+ <section>
+ <title>COMMON DATA TYPES </title>
+
+ <p>Type definitions that are used more than once in this module
+ and/or abstractions to indicate the intended use of the data
+ type:</p>
+
+ <p><c>boolean() = true | false </c></p>
+ <p><c>string() = list of ASCII characters</c></p>
+ <p><c>timeout() = infinity | integer() - in milliseconds.</c></p>
+ <p><c>ssh_connection_ref() - opaque to the user returned by
+ ssh:connect/3 or sent to a ssh channel process</c></p>
+ <p><c>ssh_channel_id() = integer() </c></p>
+ <p><c>ssh_data_type_code() = 1 ("stderr") | 0 ("normal") are
+ currently valid values see RFC 4254 section 5.2.</c></p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>call(ChannelRef, Msg) -></name>
+ <name>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 start_link/4 </d>
+ <v>Msg = term() </v>
+ <v>Timeout = timeout() </v>
+ <v>Reply = term() </v>
+ <v>Reason = closed | timeout </v>
+ </type>
+ <desc>
+ <p>Makes a synchronous call to the channel process by sending
+ a message and waiting until a reply arrives or a timeout
+ occurs. The channel will call
+ <c>CallbackModule:handle_call/3</c> to handle the message.
+ If the channel process does not exist <c>{error, closed}</c> is returned.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>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 start_link/4 </d>
+ <v>Msg = term() </v>
+ </type>
+ <desc>
+ <p>Sends an asynchronous message to the channel process and
+ returns ok immediately, ignoring if the destination node or
+ channel process does not exist. The channel will call
+ <c>CallbackModule:handle_cast/2</c> to handle the message.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>enter_loop(State) -> _ </name>
+ <fsummary> Makes an existing process into a ssh_channel process. </fsummary>
+ <type>
+ <v> State = term() - as returned by ssh_channel:init/1</v>
+ </type>
+ <desc>
+ <p> Makes an existing process into a <c>ssh_channel</c>
+ process. Does not return, instead the calling process will
+ enter the <c>ssh_channel</c> process receive loop and become a
+ <c>ssh_channel process.</c> The process must have been started using
+ one of the start functions in proc_lib, see <seealso
+ marker="stdlib:proc_lib">proc_lib(3)</seealso>. The
+ user is responsible for any initialization of the process
+ and needs to call ssh_channel:init/1.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name>
+ <fsummary> Initiates a ssh_channel process.</fsummary>
+ <type>
+ <v> Options = [{Option, Value}]</v>
+ </type>
+ <desc>
+ <p>
+ The following options must be present:
+ </p>
+ <taglist>
+ <tag><c><![CDATA[{channel_cb, atom()}]]></c></tag>
+ <item>The module that implements the channel behavior.</item>
+
+ <tag><c><![CDATA[{init_args(), list()}]]></c></tag>
+ <item> The list of arguments to the callback modules
+ init function.</item>
+
+ <tag><c><![CDATA[{cm, connection_ref()}]]></c></tag>
+ <item> Reference to the ssh connection.</item>
+
+ <tag><c><![CDATA[{channel_id, channel_id()}]]></c></tag>
+ <item> Id of the ssh channel.</item>
+
+ </taglist>
+
+ <note><p>This function is normally not called by the user, it is
+ only needed if for some reason the channel process needs
+ to be started with help of <c>proc_lib</c> instead calling
+ <c>ssh_channel:start/4</c> or <c>ssh_channel:start_link/4</c> </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name>reply(Client, Reply) -> _</name>
+ <fsummary>Send a reply to a client.</fsummary>
+ <type>
+ <v>Client - opaque to the user, see explanation below</v>
+ <v>Reply = term()</v>
+ </type>
+ <desc>
+ <p>This function can be used by a channel to explicitly send a
+ reply to a client that called <c>call/[2,3]</c> when the reply
+ cannot be defined in the return value of
+ <c>CallbackModule:handle_call/3</c>.</p>
+ <p><c>Client</c> must be the <c>From</c> argument provided to
+ the callback function <c>handle_call/3</c>.
+ <c>Reply</c> is an arbitrary term,
+ which will be given back to the client as the return value of
+ <c>ssh_channel:call/[2,3].</c></p>
+ </desc>
+ </func>
+
+ <func>
+ <name>start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> </name>
+ <name>start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
+ {ok, ChannelRef} | {error, Reason}</name>
+ <fsummary> Starts a processes that handles a ssh channel. </fsummary>
+ <type>
+ <v>SshConnection = ssh_connection_ref()</v>
+ <v>ChannelId = ssh_channel_id() </v>
+ <d> As returned by ssh_connection:session_channel/[2,4]</d>
+ <v>ChannelCb = atom()</v>
+ <d> The name of the module implementing the service specific parts
+ of the channel.</d>
+ <v>CbInitArgs = [term()]</v>
+ <d>Argument list for the init function in the callback module. </d>
+ <v>ChannelRef = pid()</v>
+ </type>
+ <desc>
+ <p>Starts a processes that handles a ssh channel. Will be
+ called internally by the ssh daemon or explicitly by the ssh
+ client implementations. A channel process traps exit signals
+ by default.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>CALLBACK FUNCTIONS</title>
+
+ <p>The functions init/1, terminate/2, handle_ssh_msg/2 and
+ handle_msg/2 are the functions that are required to provide the
+ implementation for a server side channel, such as a ssh subsystem
+ channel that can be plugged into the erlang ssh daemon see
+ <seealso marker="ssh">ssh:daemon/[2, 3]</seealso>. The
+ handle_call/3, handle_cast/2 code_change/3 and enter_loop/1
+ functions are only relevant when implementing a client side
+ channel.</p>
+ </section>
+
+ <section>
+ <marker id="cb_timeouts"></marker>
+ <title> CALLBACK TIMEOUTS</title>
+ <p> If an integer timeout value is provided in a return value of
+ one of the callback functions, a timeout will occur unless a
+ message is received within <c>Timeout</c> milliseconds. A timeout
+ is represented by the atom <c>timeout</c> which should be handled
+ by the <seealso marker="#handle_msg">handle_msg/2</seealso>
+ callback function. The atom infinity can be used to wait
+ indefinitely, this is the default value. </p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>CallbackModule:code_change(OldVsn, State, Extra) -> {ok,
+ NewState}</name>
+ <fsummary> Converts process state when code is changed.</fsummary>
+ <type>
+ <v> Converts process state when code is changed.</v>
+ </type>
+ <desc>
+ <p>This function is called by a client side channel when it
+ should update its internal state during a release
+ upgrade/downgrade, i.e. when the instruction
+ <c>{update,Module,Change,...}</c> where
+ <c>Change={advanced,Extra}</c> is given in the <c>appup</c>
+ file. See <seealso
+ marker="doc/design_principles:release_handling#instr">OTP
+ Design Principles</seealso> for more information. Any new
+ connection will benefit from a server side upgrade but
+ already started connections on the server side will not be
+ affected.
+ </p>
+
+ <note><p>If there are long lived ssh connections and more
+ than one upgrade in a short time this may cause the old
+ connections to fail as only two versions of the code may
+ be loaded simultaneously.</p></note>
+
+ <p>In the case of an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and
+ in the case of a downgrade, <c>OldVsn</c> is
+ <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the <c>vsn</c>
+ attribute(s) of the old version of the callback module
+ <c>Module</c>. If no such attribute is defined, the version
+ is the checksum of the BEAM file.</p>
+ <p><c>State</c> is the internal state of the channel.</p>
+ <p><c>Extra</c> is passed as-is from the <c>{advanced,Extra}</c>
+ part of the update instruction.</p>
+ <p>The function should return the updated internal state.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>CallbackModule: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 ssh_channel:start_link/4.</d>
+ <v> State = term() </v>
+ <v>Timeout = timeout() </v>
+ <v> Reason = term() </v>
+ </type>
+ <desc>
+ <p> Makes necessary initializations and returns the initial channel
+ state if the initializations succeed.
+ </p>
+ <p>For more detailed information on timeouts see the section
+ <seealso marker="#cb_timeouts">CALLBACK TIMEOUTS</seealso>. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>CallbackModule:handle_call(Msg, From, State) -> Result</name>
+ <fsummary> Handles messages sent by calling
+ <c>ssh_channel:call/[2,3]</c></fsummary>
+ <type>
+ <v>Msg = term()</v>
+ <v>From = opaque to the user should be used as argument to
+ ssh_channel:reply/2</v>
+ <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() - will be the return value of ssh_channel:call/[2,3]</v>
+ <v>Timeout = timeout() </v>
+ <v>NewState = term() - a possible updated version of State</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Handles messages sent by calling
+ <c>ssh_channel:call/[2,3]</c>
+ </p>
+ <p>For more detailed information on timeouts see the section
+ <seealso marker="#cb_timeouts">CALLBACK TIMEOUTS</seealso>. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>CallbackModule:handle_cast(Msg, State) -> Result</name>
+ <fsummary> Handles messages sent by calling
+ <c>ssh_channel:cact/2</c></fsummary>
+ <type>
+ <v>Msg = term()</v>
+ <v>State = term()</v>
+ <v>Result = {noreply, NewState} | {noreply, NewState, Timeout}
+ | {stop, Reason, NewState}</v>
+ <v>NewState = term() - a possible updated version of State</v>
+ <v>Timeout = timeout() </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p> Handles messages sent by calling
+ <c>ssh_channel:cast/2</c>
+ </p>
+ <p>For more detailed information on timeouts see the section
+ <seealso marker="#cb_timeouts">CALLBACK TIMEOUTS</seealso>. </p>
+ <marker id="handle_msg"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>CallbackModule:handle_msg(Msg, State) -> {ok, State} |
+ {stop, ChannelId, State}</name>
+
+ <fsummary> Handle other messages than ssh connection protocol,
+ call or cast messages sent to the channel.</fsummary>
+ <type>
+ <v>Msg = timeout | term()</v>
+ <v>State = term() </v>
+ </type>
+ <desc>
+ <p>Handle other messages than ssh connection protocol, call or
+ cast messages sent to the channel.
+ </p>
+
+ <p> Possible erlang 'EXIT'-messages should be handled by this
+ function and all channels should handle the following message.</p>
+
+ <taglist>
+ <tag><c><![CDATA[{ssh_channel_up, ssh_channel_id(),
+ ssh_connection_ref()}]]></c></tag>
+ <item>This is the first messages that will be received
+ by the channel, it is sent just before
+ the ssh_channel:init/1 function returns successfully.
+ This is especially useful if the server wants
+ to send a message to the client without first receiving
+ a message from the client. If the message is not useful
+ for your particular problem just ignore it by immediately
+ returning {ok, State}.
+ </item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>CallbackModule:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ ssh_channel_id(), State}</name>
+ <fsummary> Handles ssh connection protocol messages. </fsummary>
+ <type>
+ <v>Msg = {ssh_cm, ssh_connection_ref(), SshMsg}</v>
+ <v> SshMsg = tuple() - see message list below</v>
+ <v>State = term()</v>
+ </type>
+ <desc>
+ <p> Handles ssh connection protocol messages that may need
+ service specific attention.
+ </p>
+
+ <p> All channels should handle the following messages. For
+ channels implementing subsystems the handle_ssh_msg-callback
+ will not be called for any other messages. </p>
+
+ <taglist>
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(), {data, ssh_channel_id(),
+ ssh_data_type_code(), binary() = Data}}]]></c></tag>
+ <item> Data has arrived on the channel. When the callback
+ for this message returns the channel behavior will adjust
+ the ssh flow control window.</item>
+
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(), {eof,
+ ssh_channel_id()}}]]></c></tag>
+ <item>Indicteas that the other side will not send any more
+ data.</item>
+
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(), {signal,
+ ssh_channel_id(), ssh_signal()}} ]]></c></tag>
+ <item>A signal can be delivered to the remote
+ process/service using the following message. Some systems
+ may not implement signals, in which case they should ignore
+ this message.</item>
+
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(),
+ {exit_signal, ssh_channel_id(), string() = exit_signal,
+ string() = ErrorMsg, string() =
+ LanguageString}}]]></c></tag>
+ <item>A remote execution may terminate violently due to a
+ signal then this message may be received. For details on valid string
+ values see RFC 4254 section 6.10</item>
+
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(), {exit_status,
+ ssh_channel_id(), integer() = ExitStatus}}]]></c></tag>
+ <item> When the command running at the other end terminates,
+ the following message can be sent to return the exit status
+ of the command. A zero 'exit_status' usually means that the
+ command terminated successfully.</item>
+ </taglist>
+
+ <p> Channels implementing a shell and command execution on the server side
+ should also handle the following messages. </p>
+
+ <taglist>
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(), {env, ssh_channel_id(),
+ boolean() = WantReply, string() = Var, string() = Value}}]]></c></tag>
+ <item> Environment variables may be passed to the
+ shell/command to be started later. Note that before the
+ callback returns it should call the function
+ ssh_connection:reply_request/4 with the boolean value of <c>
+ WantReply</c> as the second argument.
+ </item>
+
+ <tag><c><![CDATA[{ssh_cm, ConnectionRef, {exec, ssh_channel_id(),
+ boolean() = WantReply, string() = Cmd}}]]></c></tag>
+ <item> This message will request that the server start the
+ execution of the given command. Note that before the
+ callback returns it should call the function
+ ssh_connection:reply_request/4 with the boolean value of <c>
+ WantReply</c> as the second argument.</item>
+
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(), {pty, ssh_channel_id(),
+ boolean() = WantReply, {string() = Terminal, integer() = CharWidth,
+ integer() = RowHeight, integer() = PixelWidth, integer() = PixelHight,
+ [{atom() | integer() = Opcode,
+ integer() = Value}] = TerminalModes}}}]]></c></tag>
+ <item>A pseudo-terminal has been requested for the
+ session. Terminal is the value of the TERM environment
+ variable value (e.g., vt100). Zero dimension parameters must
+ be ignored. The character/row dimensions override the pixel
+ dimensions (when nonzero). Pixel dimensions refer to the
+ drawable area of the window. The <c>Opcode</c> in the
+ <c>TerminalModes</c> list is the mnemonic name, represented
+ as an lowercase erlang atom, defined in RFC 4254 section 8,
+ or the opcode if the mnemonic name is not listed in the
+ RFC. Example <c>OP code: 53, mnemonic name ECHO erlang atom:
+ echo</c>. Note that before the callback returns it should
+ call the function ssh_connection:reply_request/4 with the
+ boolean value of <c> WantReply</c> as the second
+ argument.</item>
+
+ <tag><c><![CDATA[{ssh_cm, ConnectionRef, {shell, boolean() =
+ WantReply}}]]></c></tag>
+ <item> This message will request that the user's default
+ shell be started at the other end. Note that before the
+ callback returns it should call the function
+ ssh_connection:reply_request/4 with the value of <c>
+ WantReply</c> as the second argument.
+ </item>
+
+ <tag><c><![CDATA[ {ssh_cm, ssh_connection_ref(), {window_change,
+ ssh_channel_id(), integer() = CharWidth, integer() = RowHeight,
+ integer() = PixWidth, integer() = PixHeight}}]]></c></tag>
+ <item> When the window (terminal) size changes on the client
+ side, it MAY send a message to the other side to inform it
+ of the new dimensions.</item>
+ </taglist>
+
+ <p> The following message is completely taken care of by the
+ ssh channel behavior</p>
+
+ <taglist>
+ <tag><c><![CDATA[{ssh_cm, ssh_connection_ref(), {closed,
+ ssh_channel_id()}}]]></c></tag>
+ <item> The channel behavior will send a close message to the
+ other side if such a message has not already been sent and
+ then terminate the channel with reason normal.</item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>CallbackModule:terminate(Reason, State) -> _</name>
+ <fsummary> </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 ssh_connection:close/2
+ will be called if it has not been called earlier.
+ This function should be the opposite of <c>CallbackModule:init/1</c>
+ and do 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_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
new file mode 100644
index 0000000000..499cbbeabe
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2008</year>
+ <year>2008</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>ssh_connection</title>
+ <prepared>Ingela Anderton Andin</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>ssh_connection</module>
+ <modulesummary>This module provides an API to the ssh connection protocol.
+ </modulesummary>
+ <description>
+ <p>This module provides an API to the ssh connection protocol.
+ Not all features of the connection protocol are officially supported yet.
+ Only the ones supported are documented here.</p>
+ </description>
+
+ <section>
+ <title>COMMON DATA TYPES </title>
+ <p>Type definitions that are used more than once in this module and/or
+ abstractions to indicate the intended use of the data type:</p>
+
+ <p><c>boolean() = true | false </c></p>
+ <p><c>string() = list of ASCII characters</c></p>
+ <p><c>timeout() = infinity | integer() - in milliseconds.</c></p>
+ <p><c>ssh_connection_ref() - opaque to the user returned by
+ ssh:connect/3 or sent to a ssh channel processes</c></p>
+ <p><c>ssh_channel_id() = integer() </c></p>
+ <p><c>ssh_data_type_code() = 1 ("stderr") | 0 ("normal") are
+ currently valid values see RFC 4254 section 5.2.</c></p>
+ <p><c>ssh_request_status() = success | failure</c></p>
+ </section>
+
+ <section>
+ <title>MESSAGES SENT TO CHANNEL PROCESSES</title>
+
+ <p>As a result of the ssh connection protocol messages on the form
+ <c><![CDATA[{ssh_cm, ssh_connection_ref(), term()}]]></c>
+ will be sent to a channel process. The term will contain
+ information regarding the ssh connection protocol event,
+ for details see the ssh channel behavior callback <seealso
+ marker="ssh_channel">handle_ssh_msg/2 </seealso> </p>
+ </section>
+
+ <funcs>
+
+ <func>
+ <name>adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok</name>
+ <fsummary>Adjusts the ssh flowcontrol window. </fsummary>
+ <type>
+ <v> ConnectionRef = ssh_connection_ref() </v>
+ <v> ChannelId = ssh_channel_id() </v>
+ <v> NumOfBytes = integer()</v>
+ </type>
+ <desc>
+ <p>Adjusts the ssh flowcontrol window. </p>
+
+ <note><p>This will be taken care of by the ssh_channel
+ behavior when the callback <seealso marker="ssh_channel">
+ handle_ssh_msg/2 </seealso> has returned after processing a
+ {ssh_cm, ssh_connection_ref(), {data, ssh_channel_id(),
+ ssh_data_type_code(), binary()}}
+ message, and should normally not be called explicitly.</p></note>
+ </desc>
+ </func>
+
+ <func>
+ <name>close(ConnectionRef, ChannelId) -> ok</name>
+ <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>Sends a close message on the channel <c>ChannelId</c>
+ </p>
+
+ <note><p>This function will be called by the ssh channel
+ behavior when the channel is terminated see <seealso
+ marker="ssh_channel"> ssh_channel(3) </seealso> and should
+ normally not be called explicitly.</p></note>
+ </desc>
+ </func>
+
+ <func>
+ <name>exec(ConnectionRef, ChannelId, Command, TimeOut) -> ssh_request_status() </name>
+ <fsummary>Will request that the server start 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>Will request that the server start the execution of the
+ given command, the result will be received as:</p>
+
+ <taglist>
+ <tag><c> N X {ssh_cm,
+ ssh_connection_ref(), {data, ssh_channel_id(), ssh_data_type_code(),
+ binary() = Data}} </c></tag>
+ <item>The result of executing the command may be only one line
+ or thousands of lines depending on the command.</item>
+
+ <tag><c> 1 X {ssh_cm, ssh_connection_ref(), {eof, ssh_channel_id()}}</c></tag>
+ <item>Indicates that no more data will be sent.</item>
+
+ <tag><c>0 or 1 X {ssh_cm,
+ ssh_connection_ref(), {exit_signal,
+ ssh_channel_id(), string() = ExitSignal, string() = ErrorMsg, string() = LanguageString}}</c></tag>
+ <item>Not all systems send signals. For details on valid string
+ values see RFC 4254 section 6.10 </item>
+
+ <tag><c>0 or 1 X {ssh_cm, ssh_connection_ref(), {exit_status,
+ ssh_channel_id(), integer() = ExitStatus}}</c></tag>
+ <item>It is recommended by the <c>ssh connection protocol</c> that this
+ message shall be sent, but that may not always be the case.</item>
+
+ <tag><c> 1 X {ssh_cm, ssh_connection_ref(),
+ {closed, ssh_channel_id()}}</c></tag>
+ <item>Indicates that the ssh channel started for the
+ execution of the command has now been shutdown.</item>
+ </taglist>
+
+ <p> These message should be handled by the
+ client. The <seealso marker="ssh_channel">ssh channel
+ behavior</seealso> can be used when writing a client.
+ </p>
+ </desc>
+ </func>
+
+
+ <func>
+ <name>exit_status(ConnectionRef, ChannelId, Status) -> ok</name>
+ <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>Sends the exit status of a command to the client.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>reply_request(ConnectionRef, WantReply, Status, CannelId) -> ok</name>
+ <fsummary>Send 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 they want a status report e.i .<c> WantReply = true</c>,
+ if <c> WantReply</c> is false calling this function will be a
+ "noop". Should be called after handling an ssh connection
+ protocol message containing a <c>WantReply</c> boolean
+ value. See the ssh_channel behavior callback <seealso
+ marker="ssh_channel"> handle_ssh_msg/2 </seealso>
+ </p>
+ </desc>
+ </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}</name>
+ <fsummary>Sends channel data </fsummary>
+ <type>
+ <v> ConnectionRef = ssh_connection_ref() </v>
+ <v> ChannelId = ssh_channel_id()</v>
+ <v> Data = binary()</v>
+ <v> Type = ssh_data_type_code()</v>
+ <v> Timeout = timeout()</v>
+ </type>
+ <desc>
+ <p>Sends channel data.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>send_eof(ConnectionRef, ChannelId) -> ok </name>
+ <fsummary>Sends eof on the channel <c>ChannelId</c>. </fsummary>
+ <type>
+ <v> ConnectionRef = ssh_connection_ref() </v>
+ <v> ChannelId = ssh_channel_id()</v>
+ </type>
+ <desc>
+ <p>Sends eof on the 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>
+ <fsummary>Opens a channel for a ssh session. A session is a
+ remote execution of a program. The program may be a shell, an
+ application, a system command, or some built-in subsystem. </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 a ssh session. A session is a
+ remote execution of a program. The program may be a shell, an
+ application, a system command, or some built-in subsystem.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>setenv(ConnectionRef, ChannelId, Var, Value, TimeOut) -> ssh_request_status()</name>
+ <fsummary> Environment variables may 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 may be passed to the shell/command to be
+ started later.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>shell(ConnectionRef, ChannelId) -> ssh_request_status()
+ </name>
+ <fsummary> Will request that the user's default shell (typically
+ defined in /etc/passwd in UNIX systems) be started at the other
+ end. </fsummary>
+ <type>
+ <v> ConnectionRef = ssh_connection_ref() </v>
+ <v> ChannelId = ssh_channel_id()</v>
+ </type>
+ <desc>
+ <p> Will request that the user's default shell (typically
+ defined in /etc/passwd in UNIX systems) be started at the
+ other end.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>subsystem(ConnectionRef, ChannelId, Subsystem, Timeout) -> ssh_request_status()</name>
+ <fsummary> </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> Sends a request to execute a predefined subsystem.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
new file mode 100644
index 0000000000..208b2b4e72
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2005</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>ssh_sftp</title>
+ <prepared>Jakob Cederlund</prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2005-09-22</date>
+ <rev>PA1</rev>
+ <file>ssh_sftp.sgml</file>
+ </header>
+ <module>ssh_sftp</module>
+ <modulesummary>SFTP client.</modulesummary>
+ <description>
+ <p>This module implements an SFTP (SSH FTP) client. SFTP is a
+ secure, encrypted file transfer service available for
+ SSH.</p>
+ </description>
+
+ <section>
+ <title>COMMON DATA TYPES </title>
+ <p>Type definitions that are used more than once in this module
+ and/or abstractions to indicate the intended use of the data type:
+ </p>
+ <p><c>ssh_connection_ref() - opaque to the user
+ returned by ssh:connect/3</c></p>
+ <p><c>timeout() = infinity | integer() - in milliseconds.</c></p>
+ </section>
+
+ <section>
+ <title>TIMEOUTS </title>
+ <p>If the request functions for the sftp channel return {error, timeout}
+ it does not mean that the request did not reach the server and was
+ not performed, it only means that we did not receive an answer from the
+ server within the time that was expected.</p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>start_channel(ConnectionRef) -> </name>
+ <name>start_channel(ConnectionRef, Options) -> </name>
+ <name>start_channel(Host, Options) -></name>
+ <name>start_channel(Host, Port, Options) -> {ok, Pid} | {ok, Pid, ConnectionRef} |
+ {error, Reason}</name>
+ <fsummary>Starts a sftp client</fsummary>
+ <type>
+ <v>Host = string()</v>
+ <v>ConnectionRef = ssh_connection_ref()</v>
+ <v>Port = integer()</v>
+ <v>Options = [{Option, Value}]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>If not provided, setups a ssh connection in this case a
+ connection reference will be returned too. A ssh channel
+ process is started to handle the communication with the SFTP
+ server, the returned pid for this process should be used as
+ input to all other API functions in this module.</p>
+
+ <p>Options are:</p>
+ <taglist>
+ <tag><c><![CDATA[{timeout, timeout()}]]></c></tag>
+ <item>
+ <p>The timeout is passed to the ssh_channel start function,
+ and defaults to infinity.</p>
+ </item>
+ </taglist>
+ <p>All other options are directly passed to
+ <seealso marker="ssh">ssh:connect/3</seealso> or ignored if a
+ connection is already provided. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>stop_channel(ChannelPid) -> ok</name>
+ <fsummary>Stops the sftp client channel.</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ </type>
+ <desc>
+ <p>Stops a sftp channel. If the ssh connection should be closed
+ call <seealso marker="ssh">ssh:close/1</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>read_file(ChannelPid, File) -> </name>
+ <name>read_file(ChannelPid, File, Timeout) -> {ok, Data} | {error, Reason}</name>
+ <fsummary>Read a file</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>File = string()</v>
+ <v>Data = binary()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Reads a file from the server, and returns the data in a binary,
+ like <c><![CDATA[file:read_file/1]]></c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>write_file(ChannelPid, File, Iolist) -> </name>
+ <name>write_file(ChannelPid, File, Iolist, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Write a file</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>File = string()</v>
+ <v>Iolist = iolist()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Writes a file to the server, like <c><![CDATA[file:write_file/2]]></c>.
+ The file is created if it's not there.</p>
+ </desc>
+ </func>
+ <func>
+ <name>list_dir(ChannelPid, Path) -> </name>
+ <name>list_dir(ChannelPid, Path, Timeout) -> {ok, Filenames} | {error, Reason}</name>
+ <fsummary>List directory</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Path = string()</v>
+ <v>Filenames = [Filename]</v>
+ <v>Filename = string()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Lists the given directory on the server, returning the
+ filenames as a list of strings.</p>
+ </desc>
+ </func>
+ <func>
+ <name>open(ChannelPid, File, Mode) -> </name>
+ <name>open(ChannelPid, File, Mode, Timeout) -> {ok, Handle} | {error, Reason}</name>
+ <fsummary>Open a file and return 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>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Opens a file on the server, and returns a handle that
+ is used for reading or writing.</p>
+ </desc>
+ </func>
+ <func>
+ <name>opendir(ChannelPid, Path) -> </name>
+ <name>opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | {error, Reason}</name>
+ <fsummary>Open a directory and return a handle</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Path = string()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Opens a handle to a directory on the server, the handle
+ is used for reading directory contents.</p>
+ </desc>
+ </func>
+ <func>
+ <name>close(ChannelPid, Handle) -> </name>
+ <name>close(ChannelPid, Handle, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Close an open handle</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Handle = term()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Closes a handle to an open file or directory on the server.</p>
+ </desc>
+ </func>
+ <func>
+ <name>read(ChannelPid, Handle, Len) -> </name>
+ <name>read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | {error, Error}</name>
+ <name>pread(ChannelPid, Handle, Position, Len) -> </name>
+ <name>pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | {error, Error}</name>
+ <fsummary>Read 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>
+ <v>Reason = term()</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>, or <c><![CDATA[eof]]></c>, or
+ <c><![CDATA[{error, Reason}]]></c>. If the file is opened with <c><![CDATA[binary]]></c>,
+ <c><![CDATA[Data]]></c> is a binary, otherwise it is a string.</p>
+ <p>If the file is read past eof, only the remaining bytes
+ will be read and returned. If no bytes are read, <c><![CDATA[eof]]></c>
+ is returned.</p>
+ <p>The <c><![CDATA[pread]]></c> function reads from a specified position,
+ combining the <c><![CDATA[position]]></c> and <c><![CDATA[read]]></c> functions.</p>
+ </desc>
+ </func>
+ <func>
+ <name>aread(ChannelPid, Handle, Len) -> {async, N} | {error, Error}</name>
+ <name>apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, Error}</name>
+ <fsummary>Read 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>
+ <v>Reason = 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 N
+ is a term guaranteed to be unique between calls of <c><![CDATA[aread]]></c>.
+ The actual data is sent as a message to the calling process. This
+ message has the form <c><![CDATA[{async_reply, N, Result}]]></c>, where
+ <c><![CDATA[Result]]></c> is the result from the read, either <c><![CDATA[{ok, Data}]]></c>,
+ or <c><![CDATA[eof]]></c>, or <c><![CDATA[{error, Error}]]></c>.</p>
+ <p>The <c><![CDATA[apread]]></c> function reads from a specified position,
+ combining the <c><![CDATA[position]]></c> and <c><![CDATA[aread]]></c> functions.</p>
+ </desc>
+ </func>
+ <func>
+ <name>write(ChannelPid, Handle, Data) -></name>
+ <name>write(ChannelPid, Handle, Data, Timeout) -> ok | {error, Error}</name>
+ <name>pwrite(ChannelPid, Handle, Position, Data) -> ok </name>
+ <name>pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, Error}</name>
+ <fsummary>Write 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>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Write <c><![CDATA[data]]></c> to the file referenced by <c><![CDATA[Handle]]></c>.
+ The file should be opened with <c><![CDATA[write]]></c> or <c><![CDATA[append]]></c>
+ flag. Returns <c><![CDATA[ok]]></c> if successful and <c><![CDATA[{error, Reason}]]></c>
+ otherwise.</p>
+ <p>Typical error reasons are:</p>
+ <taglist>
+ <tag><c><![CDATA[ebadf]]></c></tag>
+ <item>
+ <p>The file is not opened for writing.</p>
+ </item>
+ <tag><c><![CDATA[enospc]]></c></tag>
+ <item>
+ <p>There is a no space left on the device.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name>awrite(ChannelPid, Handle, Data) -> ok | {error, Reason} </name>
+ <name>apwrite(ChannelPid, Handle, Position, Data) -> ok | {error, Reason}</name>
+ <fsummary>Write 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>Reason = term()</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 N
+ is a term guaranteed to be unique between calls of
+ <c><![CDATA[awrite]]></c>. The result of the <c><![CDATA[write]]></c> operation is sent
+ as a message to the calling process. This message has the form
+ <c><![CDATA[{async_reply, N, Result}]]></c>, where <c><![CDATA[Result]]></c> is the result
+ from the write, either <c><![CDATA[ok]]></c>, or <c><![CDATA[{error, Error}]]></c>.</p>
+ <p>The <c><![CDATA[apwrite]]></c> writes on a specified position, combining
+ the <c><![CDATA[position]]></c> and <c><![CDATA[awrite]]></c> operations.</p>
+ </desc>
+ </func>
+ <func>
+ <name>position(ChannelPid, Handle, Location) -> </name>
+ <name>position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition | {error, Error}</name>
+ <fsummary>Seek position in open 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 = int()</v>
+ <v>Timeout = timeout()</v>
+ <v>NewPosition = integer()</v>
+ <v>Reason = term()</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
+ successful, otherwise <c><![CDATA[{error, Reason}]]></c>. <c><![CDATA[Location]]></c> is
+ one of the following:</p>
+ <taglist>
+ <tag><c><![CDATA[Offset]]></c></tag>
+ <item>
+ <p>The same as <c><![CDATA[{bof, Offset}]]></c>.</p>
+ </item>
+ <tag><c><![CDATA[{bof, Offset}]]></c></tag>
+ <item>
+ <p>Absolute offset.</p>
+ </item>
+ <tag><c><![CDATA[{cur, Offset}]]></c></tag>
+ <item>
+ <p>Offset from the current position.</p>
+ </item>
+ <tag><c><![CDATA[{eof, Offset}]]></c></tag>
+ <item>
+ <p>Offset from the end of file.</p>
+ </item>
+ <tag><c><![CDATA[bof | cur | eof]]></c></tag>
+ <item>
+ <p>The same as above with <c><![CDATA[Offset]]></c> 0.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name>read_file_info(ChannelPid, Name) -> </name>
+ <name>read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, Reason}</name>
+ <fsummary>Get 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>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Returns a <c><![CDATA[file_info]]></c> record from the file specified by
+ <c><![CDATA[Name]]></c> or <c><![CDATA[Handle]]></c>, like <c><![CDATA[file:read_file_info/2]]></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>
+ <fsummary>Get 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>
+ <v>Reason = term()</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>, like
+ <c><![CDATA[file:read_link_info/2]]></c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>write_file_info(ChannelPid, Name, Info) -> </name>
+ <name>write_file_info(ChannelPid, Name, Info, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Write information for a file</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Name = string()</v>
+ <v>Info = record()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Writes file information from a <c><![CDATA[file_info]]></c> record to the
+ file specified by <c><![CDATA[Name]]></c>, like <c><![CDATA[file:write_file_info]]></c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>read_link(ChannelPid, Name) -> </name>
+ <name>read_link(ChannelPid, Name, Timeout) -> {ok, Target} | {error, Reason}</name>
+ <fsummary>Read symbolic link</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Name = string()</v>
+ <v>Target = string()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Read the link target from the symbolic link specified
+ by <c><![CDATA[name]]></c>, like <c><![CDATA[file:read_link/1]]></c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>make_symlink(ChannelPid, Name, Target) -> </name>
+ <name>make_symlink(ChannelPid, Name, Target, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Create symbolic link</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Name = string()</v>
+ <v>Target = string()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Creates a symbolic link pointing to <c><![CDATA[Target]]></c> with the
+ name <c><![CDATA[Name]]></c>, like <c><![CDATA[file:make_symlink/2]]></c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>rename(ChannelPid, OldName, NewName) -> </name>
+ <name>rename(ChannelPid, OldName, NewName, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Rename a file</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>OldName = string()</v>
+ <v>NewName = string()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Renames a file named <c><![CDATA[OldName]]></c>, and gives it the name
+ <c><![CDATA[NewName]]></c>, like <c><![CDATA[file:rename/2]]></c></p>
+ </desc>
+ </func>
+ <func>
+ <name>delete(ChannelPid, Name) -> </name>
+ <name>delete(ChannelPid, Name, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Delete a file</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Name = string()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Deletes the file specified by <c><![CDATA[Name]]></c>, like
+ <c><![CDATA[file:delete/1]]></c></p>
+ </desc>
+ </func>
+ <func>
+ <name>make_dir(ChannelPid, Name) -> </name>
+ <name>make_dir(ChannelPid, Name, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Create a directory</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Name = string()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Creates a directory specified by <c><![CDATA[Name]]></c>. <c><![CDATA[Name]]></c> should
+ be a full path to a new directory. The directory can only be
+ created in an existing directory.</p>
+ </desc>
+ </func>
+ <func>
+ <name>del_dir(ChannelPid, Name) -> </name>
+ <name>del_dir(ChannelPid, Name, Timeout) -> ok | {error, Reason}</name>
+ <fsummary>Delete an empty directory</fsummary>
+ <type>
+ <v>ChannelPid = pid()</v>
+ <v>Name = string()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Deletes a directory specified by <c><![CDATA[Name]]></c>. The directory
+ should be empty.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
+
diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml
new file mode 100644
index 0000000000..c857983565
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_sftpd.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2005</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>ssh_sftpd</title>
+ <prepared>Ingela Anderton Andin</prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2005-09-22</date>
+ <rev>PA1</rev>
+ <file>ssh_sftpd.sgml</file>
+ </header>
+ <module>ssh_sftpd</module>
+ <modulesummary>Specifies a channel process to handle a sftp subsystem.</modulesummary>
+ <description>
+ <p>Specifies a channel process to handle a sftp subsystem.</p>
+ </description>
+
+ <section>
+ <title>COMMON DATA TYPES </title>
+ <p><c>subsystem_spec() = {subsystem_name(), {channel_callback(), channel_init_args()}} </c></p>
+ <p><c>subsystem_name() = "sftp"</c></p>
+ <p><c>channel_callback() = atom()</c> - Name of the erlang module implementing the
+ subsystem using the ssh_channel behavior see
+ <seealso marker="ssh_channel">ssh_channel(3)</seealso></p>
+ <p><c> channel_init_args() = list() - The one given as argument to function
+ subsystem_spec/1.</c></p>
+ </section>
+ <funcs>
+ <func>
+ <name>subsystem_spec(Options) -> subsystem_spec()</name>
+ <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>Should be used together with ssh:daemon/[1,2,3]</p>
+ <p>Options are:</p>
+ <taglist>
+ <tag><c><![CDATA[{cwd, String}]]></c></tag>
+ <item>
+ <p>Sets the initial current working directory for the
+ server.</p>
+ </item>
+ <tag><c><![CDATA[{file_handler, CallbackModule}]]></c></tag>
+ <item>
+ <p>Determines which module to call for communicating with
+ the file server. Default value is <c>ssh_sftpd_file</c> that uses the
+ file and filelib API:s to access the standard OTP file
+ server. This option may be used to plug in the use of
+ other file servers.</p>
+ </item>
+ <tag><c><![CDATA[{max_files, Integer}]]></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>
+ <item>
+ <p>Sets the sftp root directory. The user will then not be
+ able to see any files above this root. If for instance
+ the root is set to <c>/tmp</c> the user will see this
+ directory as <c>/</c> and if the user does cd <c>/etc</c>
+ the user will end up in <c>/tmp/etc</c>.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ </funcs>
+</erlref>
+
diff --git a/lib/ssh/doc/src/user_guide.gif b/lib/ssh/doc/src/user_guide.gif
new file mode 100644
index 0000000000..e6275a803d
--- /dev/null
+++ b/lib/ssh/doc/src/user_guide.gif
Binary files differ
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps
new file mode 100644
index 0000000000..d766a933b4
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.2.ps
@@ -0,0 +1,3315 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 75 0 595 747
+%%Title: Enscript Output
+%%For: Magnus Thoang
+%%Creator: GNU enscript 1.6.1
+%%CreationDate: Fri Oct 31 13:31:26 2003
+%%Orientation: Portrait
+%%Pages: 15 0
+%%DocumentMedia: A4 595 842 0 () ()
+%%DocumentNeededResources: (atend)
+%%EndComments
+%%BeginProlog
+%%BeginProcSet: PStoPS 1 15
+userdict begin
+[/showpage/erasepage/copypage]{dup where{pop dup load
+ type/operatortype eq{1 array cvx dup 0 3 index cvx put
+ bind def}{pop}ifelse}{pop}ifelse}forall
+[/letter/legal/executivepage/a4/a4small/b5/com10envelope
+ /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
+ /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
+ {pop{}def}ifelse}{pop}ifelse}forall
+/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
+ {pop def}ifelse}{def}ifelse
+/PStoPSmatrix matrix currentmatrix def
+/PStoPSxform matrix def/PStoPSclip{clippath}def
+/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
+/initmatrix{matrix defaultmatrix setmatrix}bind def
+/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
+ [{currentpoint}stopped{$error/newerror false put{newpath}}
+ {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
+ {[/newpath cvx{/moveto cvx}{/lineto cvx}
+ {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
+ stopped{$error/errorname get/invalidaccess eq{cleartomark
+ $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
+ /initclip dup load dup type dup/operatortype eq{pop exch pop}
+ {dup/arraytype eq exch/packedarraytype eq or
+ {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
+ {pop cvx}ifelse}ifelse
+ {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
+/initgraphics{initmatrix newpath initclip 1 setlinewidth
+ 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
+ 10 setmiterlimit}bind def
+end
+%%EndProcSet
+%%BeginResource: procset Enscript-Prolog 1.6 1
+%
+% Procedures.
+%
+
+/_S { % save current state
+ /_s save def
+} def
+/_R { % restore from saved state
+ _s restore
+} def
+
+/S { % showpage protecting gstate
+ gsave
+ showpage
+ grestore
+} bind def
+
+/MF { % fontname newfontname -> - make a new encoded font
+ /newfontname exch def
+ /fontname exch def
+
+ /fontdict fontname findfont def
+ /newfont fontdict maxlength dict def
+
+ fontdict {
+ exch
+ dup /FID eq {
+ % skip FID pair
+ pop pop
+ } {
+ % copy to the new font dictionary
+ exch newfont 3 1 roll put
+ } ifelse
+ } forall
+
+ newfont /FontName newfontname put
+
+ % insert only valid encoding vectors
+ encoding_vector length 256 eq {
+ newfont /Encoding encoding_vector put
+ } if
+
+ newfontname newfont definefont pop
+} def
+
+/SF { % fontname width height -> - set a new font
+ /height exch def
+ /width exch def
+
+ findfont
+ [width 0 0 height 0 0] makefont setfont
+} def
+
+/SUF { % fontname width height -> - set a new user font
+ /height exch def
+ /width exch def
+
+ /F-gs-user-font MF
+ /F-gs-user-font width height SF
+} def
+
+/M {moveto} bind def
+/s {show} bind def
+
+/Box { % x y w h -> - define box path
+ /d_h exch def /d_w exch def /d_y exch def /d_x exch def
+ d_x d_y moveto
+ d_w 0 rlineto
+ 0 d_h rlineto
+ d_w neg 0 rlineto
+ closepath
+} def
+
+/bgs { % x y height blskip gray str -> - show string with bg color
+ /str exch def
+ /gray exch def
+ /blskip exch def
+ /height exch def
+ /y exch def
+ /x exch def
+
+ gsave
+ x y blskip sub str stringwidth pop height Box
+ gray setgray
+ fill
+ grestore
+ x y M str s
+} def
+
+% Highlight bars.
+/highlight_bars { % nlines lineheight output_y_margin gray -> -
+ gsave
+ setgray
+ /ymarg exch def
+ /lineheight exch def
+ /nlines exch def
+
+ % This 2 is just a magic number to sync highlight lines to text.
+ 0 d_header_y ymarg sub 2 sub translate
+
+ /cw d_output_w cols div def
+ /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
+
+ % for each column
+ 0 1 cols 1 sub {
+ cw mul /xp exch def
+
+ % for each rows
+ 0 1 nrows 1 sub {
+ /rn exch def
+ rn lineheight mul neg /yp exch def
+ rn nlines idiv 2 mod 0 eq {
+ % Draw highlight bar. 4 is just a magic indentation.
+ xp 4 add yp cw 8 sub lineheight neg Box fill
+ } if
+ } for
+ } for
+
+ grestore
+} def
+
+% Line highlight bar.
+/line_highlight { % x y width height gray -> -
+ gsave
+ /gray exch def
+ Box gray setgray fill
+ grestore
+} def
+
+% Column separator lines.
+/column_lines {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h translate
+ /cw d_output_w cols div def
+ 1 1 cols 1 sub {
+ cw mul 0 moveto
+ 0 d_output_h rlineto stroke
+ } for
+ grestore
+} def
+
+% Column borders.
+/column_borders {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h moveto
+ 0 d_output_h rlineto
+ d_output_w 0 rlineto
+ 0 d_output_h neg rlineto
+ closepath stroke
+ grestore
+} def
+
+% Do the actual underlay drawing
+/draw_underlay {
+ ul_style 0 eq {
+ ul_str true charpath stroke
+ } {
+ ul_str show
+ } ifelse
+} def
+
+% Underlay
+/underlay { % - -> -
+ gsave
+ 0 d_page_h translate
+ d_page_h neg d_page_w atan rotate
+
+ ul_gray setgray
+ ul_font setfont
+ /dw d_page_h dup mul d_page_w dup mul add sqrt def
+ ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
+ draw_underlay
+ grestore
+} def
+
+/user_underlay { % - -> -
+ gsave
+ ul_x ul_y translate
+ ul_angle rotate
+ ul_gray setgray
+ ul_font setfont
+ 0 0 ul_h_ptsize 2 div sub moveto
+ draw_underlay
+ grestore
+} def
+
+% Page prefeed
+/page_prefeed { % bool -> -
+ statusdict /prefeed known {
+ statusdict exch /prefeed exch put
+ } {
+ pop
+ } ifelse
+} def
+
+% Wrapped line markers
+/wrapped_line_mark { % x y charwith charheight type -> -
+ /type exch def
+ /h exch def
+ /w exch def
+ /y exch def
+ /x exch def
+
+ type 2 eq {
+ % Black boxes (like TeX does)
+ gsave
+ 0 setlinewidth
+ x w 4 div add y M
+ 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
+ closepath fill
+ grestore
+ } {
+ type 3 eq {
+ % Small arrows
+ gsave
+ .2 setlinewidth
+ x w 2 div add y h 2 div add M
+ w 4 div 0 rlineto
+ x w 4 div add y lineto stroke
+
+ x w 4 div add w 8 div add y h 4 div add M
+ x w 4 div add y lineto
+ w 4 div h 8 div rlineto stroke
+ grestore
+ } {
+ % do nothing
+ } ifelse
+ } ifelse
+} def
+
+% EPSF import.
+
+/BeginEPSF {
+ /b4_Inc_state save def % Save state for cleanup
+ /dict_count countdictstack def % Count objects on dict stack
+ /op_count count 1 sub def % Count objects on operand stack
+ userdict begin
+ /showpage { } def
+ 0 setgray 0 setlinecap
+ 1 setlinewidth 0 setlinejoin
+ 10 setmiterlimit [ ] 0 setdash newpath
+ /languagelevel where {
+ pop languagelevel
+ 1 ne {
+ false setstrokeadjust false setoverprint
+ } if
+ } if
+} bind def
+
+/EndEPSF {
+ count op_count sub { pos } repeat % Clean up stacks
+ countdictstack dict_count sub { end } repeat
+ b4_Inc_state restore
+} bind def
+
+% Check PostScript language level.
+/languagelevel where {
+ pop /gs_languagelevel languagelevel def
+} {
+ /gs_languagelevel 1 def
+} ifelse
+%%EndResource
+%%BeginResource: procset Enscript-Encoding-88591 1.6 1
+/encoding_vector [
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclam /quotedbl /numbersign
+/dollar /percent /ampersand /quoteright
+/parenleft /parenright /asterisk /plus
+/comma /hyphen /period /slash
+/zero /one /two /three
+/four /five /six /seven
+/eight /nine /colon /semicolon
+/less /equal /greater /question
+/at /A /B /C
+/D /E /F /G
+/H /I /J /K
+/L /M /N /O
+/P /Q /R /S
+/T /U /V /W
+/X /Y /Z /bracketleft
+/backslash /bracketright /asciicircum /underscore
+/quoteleft /a /b /c
+/d /e /f /g
+/h /i /j /k
+/l /m /n /o
+/p /q /r /s
+/t /u /v /w
+/x /y /z /braceleft
+/bar /braceright /tilde /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclamdown /cent /sterling
+/currency /yen /brokenbar /section
+/dieresis /copyright /ordfeminine /guillemotleft
+/logicalnot /hyphen /registered /macron
+/degree /plusminus /twosuperior /threesuperior
+/acute /mu /paragraph /bullet
+/cedilla /onesuperior /ordmasculine /guillemotright
+/onequarter /onehalf /threequarters /questiondown
+/Agrave /Aacute /Acircumflex /Atilde
+/Adieresis /Aring /AE /Ccedilla
+/Egrave /Eacute /Ecircumflex /Edieresis
+/Igrave /Iacute /Icircumflex /Idieresis
+/Eth /Ntilde /Ograve /Oacute
+/Ocircumflex /Otilde /Odieresis /multiply
+/Oslash /Ugrave /Uacute /Ucircumflex
+/Udieresis /Yacute /Thorn /germandbls
+/agrave /aacute /acircumflex /atilde
+/adieresis /aring /ae /ccedilla
+/egrave /eacute /ecircumflex /edieresis
+/igrave /iacute /icircumflex /idieresis
+/eth /ntilde /ograve /oacute
+/ocircumflex /otilde /odieresis /divide
+/oslash /ugrave /uacute /ucircumflex
+/udieresis /yacute /thorn /ydieresis
+] def
+%%EndResource
+%%EndProlog
+%%BeginSetup
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier
+/HFpt_w 10 def
+/HFpt_h 10 def
+/Courier-Bold /HF-gs-font MF
+/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
+/Courier /F-gs-font MF
+/F-gs-font 10 10 SF
+/#copies 1 def
+/d_page_w 520 def
+/d_page_h 747 def
+/d_header_x 0 def
+/d_header_y 747 def
+/d_header_w 520 def
+/d_header_h 0 def
+/d_footer_x 0 def
+/d_footer_y 0 def
+/d_footer_w 520 def
+/d_footer_h 0 def
+/d_output_w 520 def
+/d_output_h 747 def
+/cols 1 def
+userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
+ matrix invertmatrix matrix concatmatrix
+ matrix invertmatrix put
+%%EndSetup
+%%Page: (0,1) 1
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 1 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 701 M
+(Network Working Group T. Ylonen) s
+5 690 M
+(Internet-Draft SSH Communications Security Corp) s
+5 679 M
+(Expires: March 31, 2004 D. Moffat, Ed.) s
+5 668 M
+( Sun Microsystems, Inc) s
+5 657 M
+( Oct 2003) s
+5 624 M
+( SSH Protocol Architecture) s
+5 613 M
+( draft-ietf-secsh-architecture-15.txt) s
+5 591 M
+(Status of this Memo) s
+5 569 M
+( This document is an Internet-Draft and is in full conformance with) s
+5 558 M
+( all provisions of Section 10 of RFC2026.) s
+5 536 M
+( Internet-Drafts are working documents of the Internet Engineering) s
+5 525 M
+( Task Force \(IETF\), its areas, and its working groups. Note that other) s
+5 514 M
+( groups may also distribute working documents as Internet-Drafts.) s
+5 492 M
+( Internet-Drafts are draft documents valid for a maximum of six months) s
+5 481 M
+( and may be updated, replaced, or obsoleted by other documents at any) s
+5 470 M
+( time. It is inappropriate to use Internet-Drafts as reference) s
+5 459 M
+( material or to cite them other than as "work in progress.") s
+5 437 M
+( The list of current Internet-Drafts can be accessed at http://) s
+5 426 M
+( www.ietf.org/ietf/1id-abstracts.txt.) s
+5 404 M
+( The list of Internet-Draft Shadow Directories can be accessed at) s
+5 393 M
+( http://www.ietf.org/shadow.html.) s
+5 371 M
+( This Internet-Draft will expire on March 31, 2004.) s
+5 349 M
+(Copyright Notice) s
+5 327 M
+( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
+5 305 M
+(Abstract) s
+5 283 M
+( SSH is a protocol for secure remote login and other secure network) s
+5 272 M
+( services over an insecure network. This document describes the) s
+5 261 M
+( architecture of the SSH protocol, as well as the notation and) s
+5 250 M
+( terminology used in SSH protocol documents. It also discusses the SSH) s
+5 239 M
+( algorithm naming system that allows local extensions. The SSH) s
+5 228 M
+( protocol consists of three major components: The Transport Layer) s
+5 217 M
+( Protocol provides server authentication, confidentiality, and) s
+5 206 M
+( integrity with perfect forward secrecy. The User Authentication) s
+5 195 M
+( Protocol authenticates the client to the server. The Connection) s
+5 184 M
+( Protocol multiplexes the encrypted tunnel into several logical) s
+5 173 M
+( channels. Details of these protocols are described in separate) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 1]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 2 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( documents.) s
+5 668 M
+(Table of Contents) s
+5 646 M
+( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 635 M
+( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 624 M
+( 3. Specification of Requirements . . . . . . . . . . . . . . . 3) s
+5 613 M
+( 4. Architecture . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 602 M
+( 4.1 Host Keys . . . . . . . . . . . . . . . . . . . . . . . . . 4) s
+5 591 M
+( 4.2 Extensibility . . . . . . . . . . . . . . . . . . . . . . . 5) s
+5 580 M
+( 4.3 Policy Issues . . . . . . . . . . . . . . . . . . . . . . . 5) s
+5 569 M
+( 4.4 Security Properties . . . . . . . . . . . . . . . . . . . . 6) s
+5 558 M
+( 4.5 Packet Size and Overhead . . . . . . . . . . . . . . . . . . 6) s
+5 547 M
+( 4.6 Localization and Character Set Support . . . . . . . . . . . 7) s
+5 536 M
+( 5. Data Type Representations Used in the SSH Protocols . . . . 8) s
+5 525 M
+( 6. Algorithm Naming . . . . . . . . . . . . . . . . . . . . . . 10) s
+5 514 M
+( 7. Message Numbers . . . . . . . . . . . . . . . . . . . . . . 11) s
+5 503 M
+( 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . 11) s
+5 492 M
+( 9. Security Considerations . . . . . . . . . . . . . . . . . . 12) s
+5 481 M
+( 9.1 Pseudo-Random Number Generation . . . . . . . . . . . . . . 12) s
+5 470 M
+( 9.2 Transport . . . . . . . . . . . . . . . . . . . . . . . . . 13) s
+5 459 M
+( 9.2.1 Confidentiality . . . . . . . . . . . . . . . . . . . . . . 13) s
+5 448 M
+( 9.2.2 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 16) s
+5 437 M
+( 9.2.3 Replay . . . . . . . . . . . . . . . . . . . . . . . . . . . 16) s
+5 426 M
+( 9.2.4 Man-in-the-middle . . . . . . . . . . . . . . . . . . . . . 17) s
+5 415 M
+( 9.2.5 Denial-of-service . . . . . . . . . . . . . . . . . . . . . 19) s
+5 404 M
+( 9.2.6 Covert Channels . . . . . . . . . . . . . . . . . . . . . . 19) s
+5 393 M
+( 9.2.7 Forward Secrecy . . . . . . . . . . . . . . . . . . . . . . 20) s
+5 382 M
+( 9.3 Authentication Protocol . . . . . . . . . . . . . . . . . . 20) s
+5 371 M
+( 9.3.1 Weak Transport . . . . . . . . . . . . . . . . . . . . . . . 21) s
+5 360 M
+( 9.3.2 Debug messages . . . . . . . . . . . . . . . . . . . . . . . 21) s
+5 349 M
+( 9.3.3 Local security policy . . . . . . . . . . . . . . . . . . . 21) s
+5 338 M
+( 9.3.4 Public key authentication . . . . . . . . . . . . . . . . . 22) s
+5 327 M
+( 9.3.5 Password authentication . . . . . . . . . . . . . . . . . . 22) s
+5 316 M
+( 9.3.6 Host based authentication . . . . . . . . . . . . . . . . . 23) s
+5 305 M
+( 9.4 Connection protocol . . . . . . . . . . . . . . . . . . . . 23) s
+5 294 M
+( 9.4.1 End point security . . . . . . . . . . . . . . . . . . . . . 23) s
+5 283 M
+( 9.4.2 Proxy forwarding . . . . . . . . . . . . . . . . . . . . . . 23) s
+5 272 M
+( 9.4.3 X11 forwarding . . . . . . . . . . . . . . . . . . . . . . . 24) s
+5 261 M
+( Normative References . . . . . . . . . . . . . . . . . . . . 24) s
+5 250 M
+( Informative References . . . . . . . . . . . . . . . . . . . 25) s
+5 239 M
+( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 27) s
+5 228 M
+( Intellectual Property and Copyright Statements . . . . . . . 28) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 2]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (2,3) 2
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 3 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+(1. Contributors) s
+5 668 M
+( The major original contributors of this document were: Tatu Ylonen,) s
+5 657 M
+( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
+5 646 M
+( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
+5 635 M
+( Jyvaskyla\)) s
+5 613 M
+( The document editor is: [email protected]. Comments on this) s
+5 602 M
+( internet draft should be sent to the IETF SECSH working group,) s
+5 591 M
+( details at: http://ietf.org/html.charters/secsh-charter.html) s
+5 569 M
+(2. Introduction) s
+5 547 M
+( SSH is a protocol for secure remote login and other secure network) s
+5 536 M
+( services over an insecure network. It consists of three major) s
+5 525 M
+( components:) s
+5 514 M
+( o The Transport Layer Protocol [SSH-TRANS] provides server) s
+5 503 M
+( authentication, confidentiality, and integrity. It may optionally) s
+5 492 M
+( also provide compression. The transport layer will typically be) s
+5 481 M
+( run over a TCP/IP connection, but might also be used on top of any) s
+5 470 M
+( other reliable data stream.) s
+5 459 M
+( o The User Authentication Protocol [SSH-USERAUTH] authenticates the) s
+5 448 M
+( client-side user to the server. It runs over the transport layer) s
+5 437 M
+( protocol.) s
+5 426 M
+( o The Connection Protocol [SSH-CONNECT] multiplexes the encrypted) s
+5 415 M
+( tunnel into several logical channels. It runs over the user) s
+5 404 M
+( authentication protocol.) s
+5 382 M
+( The client sends a service request once a secure transport layer) s
+5 371 M
+( connection has been established. A second service request is sent) s
+5 360 M
+( after user authentication is complete. This allows new protocols to) s
+5 349 M
+( be defined and coexist with the protocols listed above.) s
+5 327 M
+( The connection protocol provides channels that can be used for a wide) s
+5 316 M
+( range of purposes. Standard methods are provided for setting up) s
+5 305 M
+( secure interactive shell sessions and for forwarding \("tunneling"\)) s
+5 294 M
+( arbitrary TCP/IP ports and X11 connections.) s
+5 272 M
+(3. Specification of Requirements) s
+5 250 M
+( All documents related to the SSH protocols shall use the keywords) s
+5 239 M
+( "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",) s
+5 228 M
+( "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" to describe) s
+5 217 M
+( requirements. They are to be interpreted as described in [RFC2119].) s
+5 195 M
+(4. Architecture) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 3]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 4 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+(4.1 Host Keys) s
+5 668 M
+( Each server host SHOULD have a host key. Hosts MAY have multiple) s
+5 657 M
+( host keys using multiple different algorithms. Multiple hosts MAY) s
+5 646 M
+( share the same host key. If a host has keys at all, it MUST have at) s
+5 635 M
+( least one key using each REQUIRED public key algorithm \(DSS) s
+5 624 M
+( [FIPS-186]\).) s
+5 602 M
+( The server host key is used during key exchange to verify that the) s
+5 591 M
+( client is really talking to the correct server. For this to be) s
+5 580 M
+( possible, the client must have a priori knowledge of the server's) s
+5 569 M
+( public host key.) s
+5 547 M
+( Two different trust models can be used:) s
+5 536 M
+( o The client has a local database that associates each host name \(as) s
+5 525 M
+( typed by the user\) with the corresponding public host key. This) s
+5 514 M
+( method requires no centrally administered infrastructure, and no) s
+5 503 M
+( third-party coordination. The downside is that the database of) s
+5 492 M
+( name-to-key associations may become burdensome to maintain.) s
+5 481 M
+( o The host name-to-key association is certified by some trusted) s
+5 470 M
+( certification authority. The client only knows the CA root key,) s
+5 459 M
+( and can verify the validity of all host keys certified by accepted) s
+5 448 M
+( CAs.) s
+5 426 M
+( The second alternative eases the maintenance problem, since) s
+5 415 M
+( ideally only a single CA key needs to be securely stored on the) s
+5 404 M
+( client. On the other hand, each host key must be appropriately) s
+5 393 M
+( certified by a central authority before authorization is possible.) s
+5 382 M
+( Also, a lot of trust is placed on the central infrastructure.) s
+5 360 M
+( The protocol provides the option that the server name - host key) s
+5 349 M
+( association is not checked when connecting to the host for the first) s
+5 338 M
+( time. This allows communication without prior communication of host) s
+5 327 M
+( keys or certification. The connection still provides protection) s
+5 316 M
+( against passive listening; however, it becomes vulnerable to active) s
+5 305 M
+( man-in-the-middle attacks. Implementations SHOULD NOT normally allow) s
+5 294 M
+( such connections by default, as they pose a potential security) s
+5 283 M
+( problem. However, as there is no widely deployed key infrastructure) s
+5 272 M
+( available on the Internet yet, this option makes the protocol much) s
+5 261 M
+( more usable during the transition time until such an infrastructure) s
+5 250 M
+( emerges, while still providing a much higher level of security than) s
+5 239 M
+( that offered by older solutions \(e.g. telnet [RFC-854] and rlogin) s
+5 228 M
+( [RFC-1282]\).) s
+5 206 M
+( Implementations SHOULD try to make the best effort to check host) s
+5 195 M
+( keys. An example of a possible strategy is to only accept a host key) s
+5 184 M
+( without checking the first time a host is connected, save the key in) s
+5 173 M
+( a local database, and compare against that key on all future) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 4]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (4,5) 3
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 5 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( connections to that host.) s
+5 668 M
+( Implementations MAY provide additional methods for verifying the) s
+5 657 M
+( correctness of host keys, e.g. a hexadecimal fingerprint derived from) s
+5 646 M
+( the SHA-1 hash of the public key. Such fingerprints can easily be) s
+5 635 M
+( verified by using telephone or other external communication channels.) s
+5 613 M
+( All implementations SHOULD provide an option to not accept host keys) s
+5 602 M
+( that cannot be verified.) s
+5 580 M
+( We believe that ease of use is critical to end-user acceptance of) s
+5 569 M
+( security solutions, and no improvement in security is gained if the) s
+5 558 M
+( new solutions are not used. Thus, providing the option not to check) s
+5 547 M
+( the server host key is believed to improve the overall security of) s
+5 536 M
+( the Internet, even though it reduces the security of the protocol in) s
+5 525 M
+( configurations where it is allowed.) s
+5 503 M
+(4.2 Extensibility) s
+5 481 M
+( We believe that the protocol will evolve over time, and some) s
+5 470 M
+( organizations will want to use their own encryption, authentication) s
+5 459 M
+( and/or key exchange methods. Central registration of all extensions) s
+5 448 M
+( is cumbersome, especially for experimental or classified features.) s
+5 437 M
+( On the other hand, having no central registration leads to conflicts) s
+5 426 M
+( in method identifiers, making interoperability difficult.) s
+5 404 M
+( We have chosen to identify algorithms, methods, formats, and) s
+5 393 M
+( extension protocols with textual names that are of a specific format.) s
+5 382 M
+( DNS names are used to create local namespaces where experimental or) s
+5 371 M
+( classified extensions can be defined without fear of conflicts with) s
+5 360 M
+( other implementations.) s
+5 338 M
+( One design goal has been to keep the base protocol as simple as) s
+5 327 M
+( possible, and to require as few algorithms as possible. However, all) s
+5 316 M
+( implementations MUST support a minimal set of algorithms to ensure) s
+5 305 M
+( interoperability \(this does not imply that the local policy on all) s
+5 294 M
+( hosts would necessary allow these algorithms\). The mandatory) s
+5 283 M
+( algorithms are specified in the relevant protocol documents.) s
+5 261 M
+( Additional algorithms, methods, formats, and extension protocols can) s
+5 250 M
+( be defined in separate drafts. See Section Algorithm Naming \(Section) s
+5 239 M
+( 6\) for more information.) s
+5 217 M
+(4.3 Policy Issues) s
+5 195 M
+( The protocol allows full negotiation of encryption, integrity, key) s
+5 184 M
+( exchange, compression, and public key algorithms and formats.) s
+5 173 M
+( Encryption, integrity, public key, and compression algorithms can be) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 5]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 6 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( different for each direction.) s
+5 668 M
+( The following policy issues SHOULD be addressed in the configuration) s
+5 657 M
+( mechanisms of each implementation:) s
+5 646 M
+( o Encryption, integrity, and compression algorithms, separately for) s
+5 635 M
+( each direction. The policy MUST specify which is the preferred) s
+5 624 M
+( algorithm \(e.g. the first algorithm listed in each category\).) s
+5 613 M
+( o Public key algorithms and key exchange method to be used for host) s
+5 602 M
+( authentication. The existence of trusted host keys for different) s
+5 591 M
+( public key algorithms also affects this choice.) s
+5 580 M
+( o The authentication methods that are to be required by the server) s
+5 569 M
+( for each user. The server's policy MAY require multiple) s
+5 558 M
+( authentication for some or all users. The required algorithms MAY) s
+5 547 M
+( depend on the location where the user is trying to log in from.) s
+5 536 M
+( o The operations that the user is allowed to perform using the) s
+5 525 M
+( connection protocol. Some issues are related to security; for) s
+5 514 M
+( example, the policy SHOULD NOT allow the server to start sessions) s
+5 503 M
+( or run commands on the client machine, and MUST NOT allow) s
+5 492 M
+( connections to the authentication agent unless forwarding such) s
+5 481 M
+( connections has been requested. Other issues, such as which TCP/) s
+5 470 M
+( IP ports can be forwarded and by whom, are clearly issues of local) s
+5 459 M
+( policy. Many of these issues may involve traversing or bypassing) s
+5 448 M
+( firewalls, and are interrelated with the local security policy.) s
+5 426 M
+(4.4 Security Properties) s
+5 404 M
+( The primary goal of the SSH protocol is improved security on the) s
+5 393 M
+( Internet. It attempts to do this in a way that is easy to deploy,) s
+5 382 M
+( even at the cost of absolute security.) s
+5 371 M
+( o All encryption, integrity, and public key algorithms used are) s
+5 360 M
+( well-known, well-established algorithms.) s
+5 349 M
+( o All algorithms are used with cryptographically sound key sizes) s
+5 338 M
+( that are believed to provide protection against even the strongest) s
+5 327 M
+( cryptanalytic attacks for decades.) s
+5 316 M
+( o All algorithms are negotiated, and in case some algorithm is) s
+5 305 M
+( broken, it is easy to switch to some other algorithm without) s
+5 294 M
+( modifying the base protocol.) s
+5 272 M
+( Specific concessions were made to make wide-spread fast deployment) s
+5 261 M
+( easier. The particular case where this comes up is verifying that) s
+5 250 M
+( the server host key really belongs to the desired host; the protocol) s
+5 239 M
+( allows the verification to be left out \(but this is NOT RECOMMENDED\).) s
+5 228 M
+( This is believed to significantly improve usability in the short) s
+5 217 M
+( term, until widespread Internet public key infrastructures emerge.) s
+5 195 M
+(4.5 Packet Size and Overhead) s
+5 173 M
+( Some readers will worry about the increase in packet size due to new) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 6]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (6,7) 4
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 7 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( headers, padding, and MAC. The minimum packet size is in the order) s
+5 679 M
+( of 28 bytes \(depending on negotiated algorithms\). The increase is) s
+5 668 M
+( negligible for large packets, but very significant for one-byte) s
+5 657 M
+( packets \(telnet-type sessions\). There are, however, several factors) s
+5 646 M
+( that make this a non-issue in almost all cases:) s
+5 635 M
+( o The minimum size of a TCP/IP header is 32 bytes. Thus, the) s
+5 624 M
+( increase is actually from 33 to 51 bytes \(roughly\).) s
+5 613 M
+( o The minimum size of the data field of an Ethernet packet is 46) s
+5 602 M
+( bytes [RFC-894]. Thus, the increase is no more than 5 bytes. When) s
+5 591 M
+( Ethernet headers are considered, the increase is less than 10) s
+5 580 M
+( percent.) s
+5 569 M
+( o The total fraction of telnet-type data in the Internet is) s
+5 558 M
+( negligible, even with increased packet sizes.) s
+5 536 M
+( The only environment where the packet size increase is likely to have) s
+5 525 M
+( a significant effect is PPP [RFC-1134] over slow modem lines \(PPP) s
+5 514 M
+( compresses the TCP/IP headers, emphasizing the increase in packet) s
+5 503 M
+( size\). However, with modern modems, the time needed to transfer is in) s
+5 492 M
+( the order of 2 milliseconds, which is a lot faster than people can) s
+5 481 M
+( type.) s
+5 459 M
+( There are also issues related to the maximum packet size. To) s
+5 448 M
+( minimize delays in screen updates, one does not want excessively) s
+5 437 M
+( large packets for interactive sessions. The maximum packet size is) s
+5 426 M
+( negotiated separately for each channel.) s
+5 404 M
+(4.6 Localization and Character Set Support) s
+5 382 M
+( For the most part, the SSH protocols do not directly pass text that) s
+5 371 M
+( would be displayed to the user. However, there are some places where) s
+5 360 M
+( such data might be passed. When applicable, the character set for the) s
+5 349 M
+( data MUST be explicitly specified. In most places, ISO 10646 with) s
+5 338 M
+( UTF-8 encoding is used [RFC-2279]. When applicable, a field is also) s
+5 327 M
+( provided for a language tag [RFC-3066].) s
+5 305 M
+( One big issue is the character set of the interactive session. There) s
+5 294 M
+( is no clear solution, as different applications may display data in) s
+5 283 M
+( different formats. Different types of terminal emulation may also be) s
+5 272 M
+( employed in the client, and the character set to be used is) s
+5 261 M
+( effectively determined by the terminal emulation. Thus, no place is) s
+5 250 M
+( provided for directly specifying the character set or encoding for) s
+5 239 M
+( terminal session data. However, the terminal emulation type \(e.g.) s
+5 228 M
+( "vt100"\) is transmitted to the remote site, and it implicitly) s
+5 217 M
+( specifies the character set and encoding. Applications typically use) s
+5 206 M
+( the terminal type to determine what character set they use, or the) s
+5 195 M
+( character set is determined using some external means. The terminal) s
+5 184 M
+( emulation may also allow configuring the default character set. In) s
+5 173 M
+( any case, the character set for the terminal session is considered) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 7]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 8 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( primarily a client local issue.) s
+5 668 M
+( Internal names used to identify algorithms or protocols are normally) s
+5 657 M
+( never displayed to users, and must be in US-ASCII.) s
+5 635 M
+( The client and server user names are inherently constrained by what) s
+5 624 M
+( the server is prepared to accept. They might, however, occasionally) s
+5 613 M
+( be displayed in logs, reports, etc. They MUST be encoded using ISO) s
+5 602 M
+( 10646 UTF-8, but other encodings may be required in some cases. It) s
+5 591 M
+( is up to the server to decide how to map user names to accepted user) s
+5 580 M
+( names. Straight bit-wise binary comparison is RECOMMENDED.) s
+5 558 M
+( For localization purposes, the protocol attempts to minimize the) s
+5 547 M
+( number of textual messages transmitted. When present, such messages) s
+5 536 M
+( typically relate to errors, debugging information, or some externally) s
+5 525 M
+( configured data. For data that is normally displayed, it SHOULD be) s
+5 514 M
+( possible to fetch a localized message instead of the transmitted) s
+5 503 M
+( message by using a numerical code. The remaining messages SHOULD be) s
+5 492 M
+( configurable.) s
+5 470 M
+(5. Data Type Representations Used in the SSH Protocols) s
+5 459 M
+( byte) s
+5 437 M
+( A byte represents an arbitrary 8-bit value \(octet\) [RFC-1700].) s
+5 426 M
+( Fixed length data is sometimes represented as an array of bytes,) s
+5 415 M
+( written byte[n], where n is the number of bytes in the array.) s
+5 393 M
+( boolean) s
+5 371 M
+( A boolean value is stored as a single byte. The value 0) s
+5 360 M
+( represents FALSE, and the value 1 represents TRUE. All non-zero) s
+5 349 M
+( values MUST be interpreted as TRUE; however, applications MUST NOT) s
+5 338 M
+( store values other than 0 and 1.) s
+5 316 M
+( uint32) s
+5 294 M
+( Represents a 32-bit unsigned integer. Stored as four bytes in the) s
+5 283 M
+( order of decreasing significance \(network byte order\). For) s
+5 272 M
+( example, the value 699921578 \(0x29b7f4aa\) is stored as 29 b7 f4) s
+5 261 M
+( aa.) s
+5 239 M
+( uint64) s
+5 217 M
+( Represents a 64-bit unsigned integer. Stored as eight bytes in) s
+5 206 M
+( the order of decreasing significance \(network byte order\).) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 8]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (8,9) 5
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 9 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( string) s
+5 668 M
+( Arbitrary length binary string. Strings are allowed to contain) s
+5 657 M
+( arbitrary binary data, including null characters and 8-bit) s
+5 646 M
+( characters. They are stored as a uint32 containing its length) s
+5 635 M
+( \(number of bytes that follow\) and zero \(= empty string\) or more) s
+5 624 M
+( bytes that are the value of the string. Terminating null) s
+5 613 M
+( characters are not used.) s
+5 591 M
+( Strings are also used to store text. In that case, US-ASCII is) s
+5 580 M
+( used for internal names, and ISO-10646 UTF-8 for text that might) s
+5 569 M
+( be displayed to the user. The terminating null character SHOULD) s
+5 558 M
+( NOT normally be stored in the string.) s
+5 536 M
+( For example, the US-ASCII string "testing" is represented as 00 00) s
+5 525 M
+( 00 07 t e s t i n g. The UTF8 mapping does not alter the encoding) s
+5 514 M
+( of US-ASCII characters.) s
+5 492 M
+( mpint) s
+5 470 M
+( Represents multiple precision integers in two's complement format,) s
+5 459 M
+( stored as a string, 8 bits per byte, MSB first. Negative numbers) s
+5 448 M
+( have the value 1 as the most significant bit of the first byte of) s
+5 437 M
+( the data partition. If the most significant bit would be set for a) s
+5 426 M
+( positive number, the number MUST be preceded by a zero byte.) s
+5 415 M
+( Unnecessary leading bytes with the value 0 or 255 MUST NOT be) s
+5 404 M
+( included. The value zero MUST be stored as a string with zero) s
+5 393 M
+( bytes of data.) s
+5 371 M
+( By convention, a number that is used in modular computations in) s
+5 360 M
+( Z_n SHOULD be represented in the range 0 <= x < n.) s
+5 338 M
+( Examples:) s
+5 327 M
+( value \(hex\) representation \(hex\)) s
+5 316 M
+( ---------------------------------------------------------------) s
+5 305 M
+( 0 00 00 00 00) s
+5 294 M
+( 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7) s
+5 283 M
+( 80 00 00 00 02 00 80) s
+5 272 M
+( -1234 00 00 00 02 ed cc) s
+5 261 M
+( -deadbeef 00 00 00 05 ff 21 52 41 11) s
+5 217 M
+( name-list) s
+5 195 M
+( A string containing a comma separated list of names. A name list) s
+5 184 M
+( is represented as a uint32 containing its length \(number of bytes) s
+5 173 M
+( that follow\) followed by a comma-separated list of zero or more) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 9]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 10 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( names. A name MUST be non-zero length, and it MUST NOT contain a) s
+5 679 M
+( comma \(','\). Context may impose additional restrictions on the) s
+5 668 M
+( names; for example, the names in a list may have to be valid) s
+5 657 M
+( algorithm identifier \(see Algorithm Naming below\), or [RFC-3066]) s
+5 646 M
+( language tags. The order of the names in a list may or may not be) s
+5 635 M
+( significant, also depending on the context where the list is is) s
+5 624 M
+( used. Terminating NUL characters are not used, neither for the) s
+5 613 M
+( individual names, nor for the list as a whole.) s
+5 591 M
+( Examples:) s
+5 580 M
+( value representation \(hex\)) s
+5 569 M
+( ---------------------------------------) s
+5 558 M
+( \(\), the empty list 00 00 00 00) s
+5 547 M
+( \("zlib"\) 00 00 00 04 7a 6c 69 62) s
+5 536 M
+( \("zlib", "none"\) 00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65) s
+5 481 M
+(6. Algorithm Naming) s
+5 459 M
+( The SSH protocols refer to particular hash, encryption, integrity,) s
+5 448 M
+( compression, and key exchange algorithms or protocols by names.) s
+5 437 M
+( There are some standard algorithms that all implementations MUST) s
+5 426 M
+( support. There are also algorithms that are defined in the protocol) s
+5 415 M
+( specification but are OPTIONAL. Furthermore, it is expected that) s
+5 404 M
+( some organizations will want to use their own algorithms.) s
+5 382 M
+( In this protocol, all algorithm identifiers MUST be printable) s
+5 371 M
+( US-ASCII non-empty strings no longer than 64 characters. Names MUST) s
+5 360 M
+( be case-sensitive.) s
+5 338 M
+( There are two formats for algorithm names:) s
+5 327 M
+( o Names that do not contain an at-sign \(@\) are reserved to be) s
+5 316 M
+( assigned by IETF consensus \(RFCs\). Examples include `3des-cbc',) s
+5 305 M
+( `sha-1', `hmac-sha1', and `zlib' \(the quotes are not part of the) s
+5 294 M
+( name\). Names of this format MUST NOT be used without first) s
+5 283 M
+( registering them. Registered names MUST NOT contain an at-sign) s
+5 272 M
+( \(@\) or a comma \(,\).) s
+5 261 M
+( o Anyone can define additional algorithms by using names in the) s
+5 250 M
+( format name@domainname, e.g. "[email protected]". The) s
+5 239 M
+( format of the part preceding the at sign is not specified; it MUST) s
+5 228 M
+( consist of US-ASCII characters except at-sign and comma. The part) s
+5 217 M
+( following the at-sign MUST be a valid fully qualified internet) s
+5 206 M
+( domain name [RFC-1034] controlled by the person or organization) s
+5 195 M
+( defining the name. It is up to each domain how it manages its) s
+5 184 M
+( local namespace.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 10]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (10,11) 6
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 11 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+(7. Message Numbers) s
+5 668 M
+( SSH packets have message numbers in the range 1 to 255. These numbers) s
+5 657 M
+( have been allocated as follows:) s
+5 624 M
+( Transport layer protocol:) s
+5 602 M
+( 1 to 19 Transport layer generic \(e.g. disconnect, ignore, debug,) s
+5 591 M
+( etc.\)) s
+5 580 M
+( 20 to 29 Algorithm negotiation) s
+5 569 M
+( 30 to 49 Key exchange method specific \(numbers can be reused for) s
+5 558 M
+( different authentication methods\)) s
+5 536 M
+( User authentication protocol:) s
+5 514 M
+( 50 to 59 User authentication generic) s
+5 503 M
+( 60 to 79 User authentication method specific \(numbers can be) s
+5 492 M
+( reused for different authentication methods\)) s
+5 470 M
+( Connection protocol:) s
+5 448 M
+( 80 to 89 Connection protocol generic) s
+5 437 M
+( 90 to 127 Channel related messages) s
+5 415 M
+( Reserved for client protocols:) s
+5 393 M
+( 128 to 191 Reserved) s
+5 371 M
+( Local extensions:) s
+5 349 M
+( 192 to 255 Local extensions) s
+5 305 M
+(8. IANA Considerations) s
+5 283 M
+( The initial state of the IANA registry is detailed in [SSH-NUMBERS].) s
+5 261 M
+( Allocation of the following types of names in the SSH protocols is) s
+5 250 M
+( assigned by IETF consensus:) s
+5 239 M
+( o SSH encryption algorithm names,) s
+5 228 M
+( o SSH MAC algorithm names,) s
+5 217 M
+( o SSH public key algorithm names \(public key algorithm also implies) s
+5 206 M
+( encoding and signature/encryption capability\),) s
+5 195 M
+( o SSH key exchange method names, and) s
+5 184 M
+( o SSH protocol \(service\) names.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 11]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 12 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( These names MUST be printable US-ASCII strings, and MUST NOT contain) s
+5 679 M
+( the characters at-sign \('@'\), comma \(','\), or whitespace or control) s
+5 668 M
+( characters \(ASCII codes 32 or less\). Names are case-sensitive, and) s
+5 657 M
+( MUST NOT be longer than 64 characters.) s
+5 635 M
+( Names with the at-sign \('@'\) in them are allocated by the owner of) s
+5 624 M
+( DNS name after the at-sign \(hierarchical allocation in [RFC-2343]\),) s
+5 613 M
+( otherwise the same restrictions as above.) s
+5 591 M
+( Each category of names listed above has a separate namespace.) s
+5 580 M
+( However, using the same name in multiple categories SHOULD be avoided) s
+5 569 M
+( to minimize confusion.) s
+5 547 M
+( Message numbers \(see Section Message Numbers \(Section 7\)\) in the) s
+5 536 M
+( range of 0..191 are allocated via IETF consensus; message numbers in) s
+5 525 M
+( the 192..255 range \(the "Local extensions" set\) are reserved for) s
+5 514 M
+( private use.) s
+5 492 M
+(9. Security Considerations) s
+5 470 M
+( In order to make the entire body of Security Considerations more) s
+5 459 M
+( accessible, Security Considerations for the transport,) s
+5 448 M
+( authentication, and connection documents have been gathered here.) s
+5 426 M
+( The transport protocol [1] provides a confidential channel over an) s
+5 415 M
+( insecure network. It performs server host authentication, key) s
+5 404 M
+( exchange, encryption, and integrity protection. It also derives a) s
+5 393 M
+( unique session id that may be used by higher-level protocols.) s
+5 371 M
+( The authentication protocol [2] provides a suite of mechanisms which) s
+5 360 M
+( can be used to authenticate the client user to the server.) s
+5 349 M
+( Individual mechanisms specified in the in authentication protocol use) s
+5 338 M
+( the session id provided by the transport protocol and/or depend on) s
+5 327 M
+( the security and integrity guarantees of the transport protocol.) s
+5 305 M
+( The connection protocol [3] specifies a mechanism to multiplex) s
+5 294 M
+( multiple streams [channels] of data over the confidential and) s
+5 283 M
+( authenticated transport. It also specifies channels for accessing an) s
+5 272 M
+( interactive shell, for 'proxy-forwarding' various external protocols) s
+5 261 M
+( over the secure transport \(including arbitrary TCP/IP protocols\), and) s
+5 250 M
+( for accessing secure 'subsystems' on the server host.) s
+5 228 M
+(9.1 Pseudo-Random Number Generation) s
+5 206 M
+( This protocol binds each session key to the session by including) s
+5 195 M
+( random, session specific data in the hash used to produce session) s
+5 184 M
+( keys. Special care should be taken to ensure that all of the random) s
+5 173 M
+( numbers are of good quality. If the random data here \(e.g., DH) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 12]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (12,13) 7
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 13 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( parameters\) are pseudo-random then the pseudo-random number generator) s
+5 679 M
+( should be cryptographically secure \(i.e., its next output not easily) s
+5 668 M
+( guessed even when knowing all previous outputs\) and, furthermore,) s
+5 657 M
+( proper entropy needs to be added to the pseudo-random number) s
+5 646 M
+( generator. RFC 1750 [1750] offers suggestions for sources of random) s
+5 635 M
+( numbers and entropy. Implementors should note the importance of) s
+5 624 M
+( entropy and the well-meant, anecdotal warning about the difficulty in) s
+5 613 M
+( properly implementing pseudo-random number generating functions.) s
+5 591 M
+( The amount of entropy available to a given client or server may) s
+5 580 M
+( sometimes be less than what is required. In this case one must) s
+5 569 M
+( either resort to pseudo-random number generation regardless of) s
+5 558 M
+( insufficient entropy or refuse to run the protocol. The latter is) s
+5 547 M
+( preferable.) s
+5 525 M
+(9.2 Transport) s
+5 503 M
+(9.2.1 Confidentiality) s
+5 481 M
+( It is beyond the scope of this document and the Secure Shell Working) s
+5 470 M
+( Group to analyze or recommend specific ciphers other than the ones) s
+5 459 M
+( which have been established and accepted within the industry. At the) s
+5 448 M
+( time of this writing, ciphers commonly in use include 3DES, ARCFOUR,) s
+5 437 M
+( twofish, serpent and blowfish. AES has been accepted by The) s
+5 426 M
+( published as a US Federal Information Processing Standards [FIPS-197]) s
+5 415 M
+( and the cryptographic community as being acceptable for this purpose) s
+5 404 M
+( as well has accepted AES. As always, implementors and users should) s
+5 393 M
+( check current literature to ensure that no recent vulnerabilities) s
+5 382 M
+( have been found in ciphers used within products. Implementors should) s
+5 371 M
+( also check to see which ciphers are considered to be relatively) s
+5 360 M
+( stronger than others and should recommend their use to users over) s
+5 349 M
+( relatively weaker ciphers. It would be considered good form for an) s
+5 338 M
+( implementation to politely and unobtrusively notify a user that a) s
+5 327 M
+( stronger cipher is available and should be used when a weaker one is) s
+5 316 M
+( actively chosen.) s
+5 294 M
+( The "none" cipher is provided for debugging and SHOULD NOT be used) s
+5 283 M
+( except for that purpose. It's cryptographic properties are) s
+5 272 M
+( sufficiently described in RFC 2410, which will show that its use does) s
+5 261 M
+( not meet the intent of this protocol.) s
+5 239 M
+( The relative merits of these and other ciphers may also be found in) s
+5 228 M
+( current literature. Two references that may provide information on) s
+5 217 M
+( the subject are [SCHNEIER] and [KAUFMAN,PERLMAN,SPECINER]. Both of) s
+5 206 M
+( these describe the CBC mode of operation of certain ciphers and the) s
+5 195 M
+( weakness of this scheme. Essentially, this mode is theoretically) s
+5 184 M
+( vulnerable to chosen cipher-text attacks because of the high) s
+5 173 M
+( predictability of the start of packet sequence. However, this attack) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 13]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 14 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( is still deemed difficult and not considered fully practicable) s
+5 679 M
+( especially if relatively longer block sizes are used.) s
+5 657 M
+( Additionally, another CBC mode attack may be mitigated through the) s
+5 646 M
+( insertion of packets containing SSH_MSG_IGNORE. Without this) s
+5 635 M
+( technique, a specific attack may be successful. For this attack) s
+5 624 M
+( \(commonly known as the Rogaway attack) s
+5 613 M
+( [ROGAWAY],[DAI],[BELLARE,KOHNO,NAMPREMPRE]\) to work, the attacker) s
+5 602 M
+( would need to know the IV of the next block that is going to be) s
+5 591 M
+( encrypted. In CBC mode that is the output of the encryption of the) s
+5 580 M
+( previous block. If the attacker does not have any way to see the) s
+5 569 M
+( packet yet \(i.e it is in the internal buffers of the ssh) s
+5 558 M
+( implementation or even in the kernel\) then this attack will not work.) s
+5 547 M
+( If the last packet has been sent out to the network \(i.e the attacker) s
+5 536 M
+( has access to it\) then he can use the attack.) s
+5 514 M
+( In the optimal case an implementor would need to add an extra packet) s
+5 503 M
+( only if the packet has been sent out onto the network and there are) s
+5 492 M
+( no other packets waiting for transmission. Implementors may wish to) s
+5 481 M
+( check to see if there are any unsent packets awaiting transmission,) s
+5 470 M
+( but unfortunately it is not normally easy to obtain this information) s
+5 459 M
+( from the kernel or buffers. If there are not, then a packet) s
+5 448 M
+( containing SSH_MSG_IGNORE SHOULD be sent. If a new packet is added) s
+5 437 M
+( to the stream every time the attacker knows the IV that is supposed) s
+5 426 M
+( to be used for the next packet, then the attacker will not be able to) s
+5 415 M
+( guess the correct IV, thus the attack will never be successfull.) s
+5 393 M
+( As an example, consider the following case:) s
+5 360 M
+( Client Server) s
+5 349 M
+( ------ ------) s
+5 338 M
+( TCP\(seq=x, len=500\) ->) s
+5 327 M
+( contains Record 1) s
+5 305 M
+( [500 ms passes, no ACK]) s
+5 283 M
+( TCP\(seq=x, len=1000\) ->) s
+5 272 M
+( contains Records 1,2) s
+5 250 M
+( ACK) s
+5 217 M
+( 1. The Nagle algorithm + TCP retransmits mean that the two records) s
+5 206 M
+( get coalesced into a single TCP segment) s
+5 195 M
+( 2. Record 2 is *not* at the beginning of the TCP segment and never) s
+5 184 M
+( will be, since it gets ACKed.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 14]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (14,15) 8
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 15 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( 3. Yet, the attack is possible because Record 1 has already been) s
+5 679 M
+( seen.) s
+5 657 M
+( As this example indicates, it's totally unsafe to use the existence) s
+5 646 M
+( of unflushed data in the TCP buffers proper as a guide to whether you) s
+5 635 M
+( need an empty packet, since when you do the second write\(\), the) s
+5 624 M
+( buffers will contain the un-ACKed Record 1.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 15]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 16 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( On the other hand, it's perfectly safe to have the following) s
+5 679 M
+( situation:) s
+5 646 M
+( Client Server) s
+5 635 M
+( ------ ------) s
+5 624 M
+( TCP\(seq=x, len=500\) ->) s
+5 613 M
+( contains SSH_MSG_IGNORE) s
+5 591 M
+( TCP\(seq=y, len=500\) ->) s
+5 580 M
+( contains Data) s
+5 558 M
+( Provided that the IV for second SSH Record is fixed after the data for) s
+5 547 M
+( the Data packet is determined -i.e. you do:) s
+5 536 M
+( read from user) s
+5 525 M
+( encrypt null packet) s
+5 514 M
+( encrypt data packet) s
+5 481 M
+(9.2.2 Data Integrity) s
+5 459 M
+( This protocol does allow the Data Integrity mechanism to be disabled.) s
+5 448 M
+( Implementors SHOULD be wary of exposing this feature for any purpose) s
+5 437 M
+( other than debugging. Users and administrators SHOULD be explicitly) s
+5 426 M
+( warned anytime the "none" MAC is enabled.) s
+5 404 M
+( So long as the "none" MAC is not used, this protocol provides data) s
+5 393 M
+( integrity.) s
+5 371 M
+( Because MACs use a 32 bit sequence number, they might start to leak) s
+5 360 M
+( information after 2**32 packets have been sent. However, following) s
+5 349 M
+( the rekeying recommendations should prevent this attack. The) s
+5 338 M
+( transport protocol [1] recommends rekeying after one gigabyte of) s
+5 327 M
+( data, and the smallest possible packet is 16 bytes. Therefore,) s
+5 316 M
+( rekeying SHOULD happen after 2**28 packets at the very most.) s
+5 294 M
+(9.2.3 Replay) s
+5 272 M
+( The use of a MAC other than 'none' provides integrity and) s
+5 261 M
+( authentication. In addition, the transport protocol provides a) s
+5 250 M
+( unique session identifier \(bound in part to pseudo-random data that) s
+5 239 M
+( is part of the algorithm and key exchange process\) that can be used) s
+5 228 M
+( by higher level protocols to bind data to a given session and prevent) s
+5 217 M
+( replay of data from prior sessions. For example, the authentication) s
+5 206 M
+( protocol uses this to prevent replay of signatures from previous) s
+5 195 M
+( sessions. Because public key authentication exchanges are) s
+5 184 M
+( cryptographically bound to the session \(i.e., to the initial key) s
+5 173 M
+( exchange\) they cannot be successfully replayed in other sessions.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 16]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (16,17) 9
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 17 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( Note that the session ID can be made public without harming the) s
+5 679 M
+( security of the protocol.) s
+5 657 M
+( If two session happen to have the same session ID [hash of key) s
+5 646 M
+( exchanges] then packets from one can be replayed against the other.) s
+5 635 M
+( It must be stressed that the chances of such an occurrence are,) s
+5 624 M
+( needless to say, minimal when using modern cryptographic methods.) s
+5 613 M
+( This is all the more so true when specifying larger hash function) s
+5 602 M
+( outputs and DH parameters.) s
+5 580 M
+( Replay detection using monotonically increasing sequence numbers as) s
+5 569 M
+( input to the MAC, or HMAC in some cases, is described in [RFC2085] />) s
+5 558 M
+( [RFC2246], [RFC2743], [RFC1964], [RFC2025], and [RFC1510]. The) s
+5 547 M
+( underlying construct is discussed in [RFC2104]. Essentially a) s
+5 536 M
+( different sequence number in each packet ensures that at least this) s
+5 525 M
+( one input to the MAC function will be unique and will provide a) s
+5 514 M
+( nonrecurring MAC output that is not predictable to an attacker. If) s
+5 503 M
+( the session stays active long enough, however, this sequence number) s
+5 492 M
+( will wrap. This event may provide an attacker an opportunity to) s
+5 481 M
+( replay a previously recorded packet with an identical sequence number) s
+5 470 M
+( but only if the peers have not rekeyed since the transmission of the) s
+5 459 M
+( first packet with that sequence number. If the peers have rekeyed,) s
+5 448 M
+( then the replay will be detected as the MAC check will fail. For) s
+5 437 M
+( this reason, it must be emphasized that peers MUST rekey before a) s
+5 426 M
+( wrap of the sequence numbers. Naturally, if an attacker does attempt) s
+5 415 M
+( to replay a captured packet before the peers have rekeyed, then the) s
+5 404 M
+( receiver of the duplicate packet will not be able to validate the MAC) s
+5 393 M
+( and it will be discarded. The reason that the MAC will fail is) s
+5 382 M
+( because the receiver will formulate a MAC based upon the packet) s
+5 371 M
+( contents, the shared secret, and the expected sequence number. Since) s
+5 360 M
+( the replayed packet will not be using that expected sequence number) s
+5 349 M
+( \(the sequence number of the replayed packet will have already been) s
+5 338 M
+( passed by the receiver\) then the calculated MAC will not match the) s
+5 327 M
+( MAC received with the packet.) s
+5 305 M
+(9.2.4 Man-in-the-middle) s
+5 283 M
+( This protocol makes no assumptions nor provisions for an) s
+5 272 M
+( infrastructure or means for distributing the public keys of hosts. It) s
+5 261 M
+( is expected that this protocol will sometimes be used without first) s
+5 250 M
+( verifying the association between the server host key and the server) s
+5 239 M
+( host name. Such usage is vulnerable to man-in-the-middle attacks.) s
+5 228 M
+( This section describes this and encourages administrators and users) s
+5 217 M
+( to understand the importance of verifying this association before any) s
+5 206 M
+( session is initiated.) s
+5 184 M
+( There are three cases of man-in-the-middle attacks to consider. The) s
+5 173 M
+( first is where an attacker places a device between the client and the) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 17]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 18 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( server before the session is initiated. In this case, the attack) s
+5 679 M
+( device is trying to mimic the legitimate server and will offer its) s
+5 668 M
+( public key to the client when the client initiates a session. If it) s
+5 657 M
+( were to offer the public key of the server, then it would not be able) s
+5 646 M
+( to decrypt or sign the transmissions between the legitimate server) s
+5 635 M
+( and the client unless it also had access to the private-key of the) s
+5 624 M
+( host. The attack device will also, simultaneously to this, initiate) s
+5 613 M
+( a session to the legitimate server masquerading itself as the client.) s
+5 602 M
+( If the public key of the server had been securely distributed to the) s
+5 591 M
+( client prior to that session initiation, the key offered to the) s
+5 580 M
+( client by the attack device will not match the key stored on the) s
+5 569 M
+( client. In that case, the user SHOULD be given a warning that the) s
+5 558 M
+( offered host key does not match the host key cached on the client.) s
+5 547 M
+( As described in Section 3.1 of [ARCH], the user may be free to accept) s
+5 536 M
+( the new key and continue the session. It is RECOMMENDED that the) s
+5 525 M
+( warning provide sufficient information to the user of the client) s
+5 514 M
+( device so they may make an informed decision. If the user chooses to) s
+5 503 M
+( continue the session with the stored public-key of the server \(not) s
+5 492 M
+( the public-key offered at the start of the session\), then the session) s
+5 481 M
+( specific data between the attacker and server will be different) s
+5 470 M
+( between the client-to-attacker session and the attacker-to-server) s
+5 459 M
+( sessions due to the randomness discussed above. From this, the) s
+5 448 M
+( attacker will not be able to make this attack work since the attacker) s
+5 437 M
+( will not be able to correctly sign packets containing this session) s
+5 426 M
+( specific data from the server since he does not have the private key) s
+5 415 M
+( of that server.) s
+5 393 M
+( The second case that should be considered is similar to the first) s
+5 382 M
+( case in that it also happens at the time of connection but this case) s
+5 371 M
+( points out the need for the secure distribution of server public) s
+5 360 M
+( keys. If the server public keys are not securely distributed then) s
+5 349 M
+( the client cannot know if it is talking to the intended server. An) s
+5 338 M
+( attacker may use social engineering techniques to pass off server) s
+5 327 M
+( keys to unsuspecting users and may then place a man-in-the-middle) s
+5 316 M
+( attack device between the legitimate server and the clients. If this) s
+5 305 M
+( is allowed to happen then the clients will form client-to-attacker) s
+5 294 M
+( sessions and the attacker will form attacker-to-server sessions and) s
+5 283 M
+( will be able to monitor and manipulate all of the traffic between the) s
+5 272 M
+( clients and the legitimate servers. Server administrators are) s
+5 261 M
+( encouraged to make host key fingerprints available for checking by) s
+5 250 M
+( some means whose security does not rely on the integrity of the) s
+5 239 M
+( actual host keys. Possible mechanisms are discussed in Section 3.1) s
+5 228 M
+( of [SSH-ARCH] and may also include secured Web pages, physical pieces) s
+5 217 M
+( of paper, etc. Implementors SHOULD provide recommendations on how) s
+5 206 M
+( best to do this with their implementation. Because the protocol is) s
+5 195 M
+( extensible, future extensions to the protocol may provide better) s
+5 184 M
+( mechanisms for dealing with the need to know the server's host key) s
+5 173 M
+( before connecting. For example, making the host key fingerprint) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 18]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (18,19) 10
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 19 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( available through a secure DNS lookup, or using kerberos over gssapi) s
+5 679 M
+( during key exchange to authenticate the server are possibilities.) s
+5 657 M
+( In the third man-in-the-middle case, attackers may attempt to) s
+5 646 M
+( manipulate packets in transit between peers after the session has) s
+5 635 M
+( been established. As described in the Replay part of this section, a) s
+5 624 M
+( successful attack of this nature is very improbable. As in the) s
+5 613 M
+( Replay section, this reasoning does assume that the MAC is secure and) s
+5 602 M
+( that it is infeasible to construct inputs to a MAC algorithm to give) s
+5 591 M
+( a known output. This is discussed in much greater detail in Section) s
+5 580 M
+( 6 of RFC 2104. If the MAC algorithm has a vulnerability or is weak) s
+5 569 M
+( enough, then the attacker may be able to specify certain inputs to) s
+5 558 M
+( yield a known MAC. With that they may be able to alter the contents) s
+5 547 M
+( of a packet in transit. Alternatively the attacker may be able to) s
+5 536 M
+( exploit the algorithm vulnerability or weakness to find the shared) s
+5 525 M
+( secret by reviewing the MACs from captured packets. In either of) s
+5 514 M
+( those cases, an attacker could construct a packet or packets that) s
+5 503 M
+( could be inserted into an SSH stream. To prevent that, implementors) s
+5 492 M
+( are encouraged to utilize commonly accepted MAC algorithms and) s
+5 481 M
+( administrators are encouraged to watch current literature and) s
+5 470 M
+( discussions of cryptography to ensure that they are not using a MAC) s
+5 459 M
+( algorithm that has a recently found vulnerability or weakness.) s
+5 437 M
+( In summary, the use of this protocol without a reliable association) s
+5 426 M
+( of the binding between a host and its host keys is inherently) s
+5 415 M
+( insecure and is NOT RECOMMENDED. It may however be necessary in) s
+5 404 M
+( non-security critical environments, and will still provide protection) s
+5 393 M
+( against passive attacks. Implementors of protocols and applications) s
+5 382 M
+( running on top of this protocol should keep this possibility in mind.) s
+5 360 M
+(9.2.5 Denial-of-service) s
+5 338 M
+( This protocol is designed to be used over a reliable transport. If) s
+5 327 M
+( transmission errors or message manipulation occur, the connection is) s
+5 316 M
+( closed. The connection SHOULD be re-established if this occurs.) s
+5 305 M
+( Denial of service attacks of this type \("wire cutter"\) are almost) s
+5 294 M
+( impossible to avoid.) s
+5 272 M
+( In addition, this protocol is vulnerable to Denial of Service attacks) s
+5 261 M
+( because an attacker can force the server to go through the CPU and) s
+5 250 M
+( memory intensive tasks of connection setup and key exchange without) s
+5 239 M
+( authenticating. Implementors SHOULD provide features that make this) s
+5 228 M
+( more difficult. For example, only allowing connections from a subset) s
+5 217 M
+( of IPs known to have valid users.) s
+5 195 M
+(9.2.6 Covert Channels) s
+5 173 M
+( The protocol was not designed to eliminate covert channels. For) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 19]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 20 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( example, the padding, SSH_MSG_IGNORE messages, and several other) s
+5 679 M
+( places in the protocol can be used to pass covert information, and) s
+5 668 M
+( the recipient has no reliable way to verify whether such information) s
+5 657 M
+( is being sent.) s
+5 635 M
+(9.2.7 Forward Secrecy) s
+5 613 M
+( It should be noted that the Diffie-Hellman key exchanges may provide) s
+5 602 M
+( perfect forward secrecy \(PFS\). PFS is essentially defined as the) s
+5 591 M
+( cryptographic property of a key-establishment protocol in which the) s
+5 580 M
+( compromise of a session key or long-term private key after a given) s
+5 569 M
+( session does not cause the compromise of any earlier session. [ANSI) s
+5 558 M
+( T1.523-2001] SSHv2 sessions resulting from a key exchange using) s
+5 547 M
+( diffie-hellman-group1-sha1 are secure even if private keying/) s
+5 536 M
+( authentication material is later revealed, but not if the session) s
+5 525 M
+( keys are revealed. So, given this definition of PFS, SSHv2 does have) s
+5 514 M
+( PFS. It is hoped that all other key exchange mechanisms proposed and) s
+5 503 M
+( used in the future will also provide PFS. This property is not) s
+5 492 M
+( commuted to any of the applications or protocols using SSH as a) s
+5 481 M
+( transport however. The transport layer of SSH provides) s
+5 470 M
+( confidentiality for password authentication and other methods that) s
+5 459 M
+( rely on secret data.) s
+5 437 M
+( Of course, if the DH private parameters for the client and server are) s
+5 426 M
+( revealed then the session key is revealed, but these items can be) s
+5 415 M
+( thrown away after the key exchange completes. It's worth pointing) s
+5 404 M
+( out that these items should not be allowed to end up on swap space) s
+5 393 M
+( and that they should be erased from memory as soon as the key) s
+5 382 M
+( exchange completes.) s
+5 360 M
+(9.3 Authentication Protocol) s
+5 338 M
+( The purpose of this protocol is to perform client user) s
+5 327 M
+( authentication. It assumes that this run over a secure transport) s
+5 316 M
+( layer protocol, which has already authenticated the server machine,) s
+5 305 M
+( established an encrypted communications channel, and computed a) s
+5 294 M
+( unique session identifier for this session.) s
+5 272 M
+( Several authentication methods with different security) s
+5 261 M
+( characteristics are allowed. It is up to the server's local policy) s
+5 250 M
+( to decide which methods \(or combinations of methods\) it is willing to) s
+5 239 M
+( accept for each user. Authentication is no stronger than the weakest) s
+5 228 M
+( combination allowed.) s
+5 206 M
+( The server may go into a "sleep" period after repeated unsuccessful) s
+5 195 M
+( authentication attempts to make key search more difficult for) s
+5 184 M
+( attackers. Care should be taken so that this doesn't become a) s
+5 173 M
+( self-denial of service vector.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 20]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (20,21) 11
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 21 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+(9.3.1 Weak Transport) s
+5 668 M
+( If the transport layer does not provide confidentiality,) s
+5 657 M
+( authentication methods that rely on secret data SHOULD be disabled.) s
+5 646 M
+( If it does not provide strong integrity protection, requests to) s
+5 635 M
+( change authentication data \(e.g. a password change\) SHOULD be) s
+5 624 M
+( disabled to prevent an attacker from modifying the ciphertext) s
+5 613 M
+( without being noticed, or rendering the new authentication data) s
+5 602 M
+( unusable \(denial of service\).) s
+5 580 M
+( The assumption as stated above that the Authentication Protocol only) s
+5 569 M
+( run over a secure transport that has previously authenticated the) s
+5 558 M
+( server is very important to note. People deploying SSH are reminded) s
+5 547 M
+( of the consequences of man-in-the-middle attacks if the client does) s
+5 536 M
+( not have a very strong a priori association of the server with the) s
+5 525 M
+( host key of that server. Specifically for the case of the) s
+5 514 M
+( Authentication Protocol the client may form a session to a) s
+5 503 M
+( man-in-the-middle attack device and divulge user credentials such as) s
+5 492 M
+( their username and password. Even in the cases of authentication) s
+5 481 M
+( where no user credentials are divulged, an attacker may still gain) s
+5 470 M
+( information they shouldn't have by capturing key-strokes in much the) s
+5 459 M
+( same way that a honeypot works.) s
+5 437 M
+(9.3.2 Debug messages) s
+5 415 M
+( Special care should be taken when designing debug messages. These) s
+5 404 M
+( messages may reveal surprising amounts of information about the host) s
+5 393 M
+( if not properly designed. Debug messages can be disabled \(during) s
+5 382 M
+( user authentication phase\) if high security is required.) s
+5 371 M
+( Administrators of host machines should make all attempts to) s
+5 360 M
+( compartmentalize all event notification messages and protect them) s
+5 349 M
+( from unwarranted observation. Developers should be aware of the) s
+5 338 M
+( sensitive nature of some of the normal event messages and debug) s
+5 327 M
+( messages and may want to provide guidance to administrators on ways) s
+5 316 M
+( to keep this information away from unauthorized people. Developers) s
+5 305 M
+( should consider minimizing the amount of sensitive information) s
+5 294 M
+( obtainable by users during the authentication phase in accordance) s
+5 283 M
+( with the local policies. For this reason, it is RECOMMENDED that) s
+5 272 M
+( debug messages be initially disabled at the time of deployment and) s
+5 261 M
+( require an active decision by an administrator to allow them to be) s
+5 250 M
+( enabled. It is also RECOMMENDED that a message expressing this) s
+5 239 M
+( concern be presented to the administrator of a system when the action) s
+5 228 M
+( is taken to enable debugging messages.) s
+5 206 M
+(9.3.3 Local security policy) s
+5 184 M
+( Implementer MUST ensure that the credentials provided validate the) s
+5 173 M
+( professed user and also MUST ensure that the local policy of the) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 21]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 22 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( server permits the user the access requested. In particular, because) s
+5 679 M
+( of the flexible nature of the SSH connection protocol, it may not be) s
+5 668 M
+( possible to determine the local security policy, if any, that should) s
+5 657 M
+( apply at the time of authentication because the kind of service being) s
+5 646 M
+( requested is not clear at that instant. For example, local policy) s
+5 635 M
+( might allow a user to access files on the server, but not start an) s
+5 624 M
+( interactive shell. However, during the authentication protocol, it is) s
+5 613 M
+( not known whether the user will be accessing files or attempting to) s
+5 602 M
+( use an interactive shell, or even both. In any event, where local) s
+5 591 M
+( security policy for the server host exists, it MUST be applied and) s
+5 580 M
+( enforced correctly.) s
+5 558 M
+( Implementors are encouraged to provide a default local policy and) s
+5 547 M
+( make its parameters known to administrators and users. At the) s
+5 536 M
+( discretion of the implementors, this default policy may be along the) s
+5 525 M
+( lines of 'anything goes' where there are no restrictions placed upon) s
+5 514 M
+( users, or it may be along the lines of 'excessively restrictive' in) s
+5 503 M
+( which case the administrators will have to actively make changes to) s
+5 492 M
+( this policy to meet their needs. Alternatively, it may be some) s
+5 481 M
+( attempt at providing something practical and immediately useful to) s
+5 470 M
+( the administrators of the system so they don't have to put in much) s
+5 459 M
+( effort to get SSH working. Whatever choice is made MUST be applied) s
+5 448 M
+( and enforced as required above.) s
+5 426 M
+(9.3.4 Public key authentication) s
+5 404 M
+( The use of public-key authentication assumes that the client host has) s
+5 393 M
+( not been compromised. It also assumes that the private-key of the) s
+5 382 M
+( server host has not been compromised.) s
+5 360 M
+( This risk can be mitigated by the use of passphrases on private keys;) s
+5 349 M
+( however, this is not an enforceable policy. The use of smartcards,) s
+5 338 M
+( or other technology to make passphrases an enforceable policy is) s
+5 327 M
+( suggested.) s
+5 305 M
+( The server could require both password and public-key authentication,) s
+5 294 M
+( however, this requires the client to expose its password to the) s
+5 283 M
+( server \(see section on password authentication below.\)) s
+5 261 M
+(9.3.5 Password authentication) s
+5 239 M
+( The password mechanism as specified in the authentication protocol) s
+5 228 M
+( assumes that the server has not been compromised. If the server has) s
+5 217 M
+( been compromised, using password authentication will reveal a valid) s
+5 206 M
+( username / password combination to the attacker, which may lead to) s
+5 195 M
+( further compromises.) s
+5 173 M
+( This vulnerability can be mitigated by using an alternative form of) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 22]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (22,23) 12
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 23 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( authentication. For example, public-key authentication makes no) s
+5 679 M
+( assumptions about security on the server.) s
+5 657 M
+(9.3.6 Host based authentication) s
+5 635 M
+( Host based authentication assumes that the client has not been) s
+5 624 M
+( compromised. There are no mitigating strategies, other than to use) s
+5 613 M
+( host based authentication in combination with another authentication) s
+5 602 M
+( method.) s
+5 580 M
+(9.4 Connection protocol) s
+5 558 M
+(9.4.1 End point security) s
+5 536 M
+( End point security is assumed by the connection protocol. If the) s
+5 525 M
+( server has been compromised, any terminal sessions, port forwarding,) s
+5 514 M
+( or systems accessed on the host are compromised. There are no) s
+5 503 M
+( mitigating factors for this.) s
+5 481 M
+( If the client end point has been compromised, and the server fails to) s
+5 470 M
+( stop the attacker at the authentication protocol, all services) s
+5 459 M
+( exposed \(either as subsystems or through forwarding\) will be) s
+5 448 M
+( vulnerable to attack. Implementors SHOULD provide mechanisms for) s
+5 437 M
+( administrators to control which services are exposed to limit the) s
+5 426 M
+( vulnerability of other services.) s
+5 404 M
+( These controls might include controlling which machines and ports can) s
+5 393 M
+( be target in 'port-forwarding' operations, which users are allowed to) s
+5 382 M
+( use interactive shell facilities, or which users are allowed to use) s
+5 371 M
+( exposed subsystems.) s
+5 349 M
+(9.4.2 Proxy forwarding) s
+5 327 M
+( The SSH connection protocol allows for proxy forwarding of other) s
+5 316 M
+( protocols such as SNMP, POP3, and HTTP. This may be a concern for) s
+5 305 M
+( network administrators who wish to control the access of certain) s
+5 294 M
+( applications by users located outside of their physical location.) s
+5 283 M
+( Essentially, the forwarding of these protocols may violate site) s
+5 272 M
+( specific security policies as they may be undetectably tunneled) s
+5 261 M
+( through a firewall. Implementors SHOULD provide an administrative) s
+5 250 M
+( mechanism to control the proxy forwarding functionality so that site) s
+5 239 M
+( specific security policies may be upheld.) s
+5 217 M
+( In addition, a reverse proxy forwarding functionality is available,) s
+5 206 M
+( which again can be used to bypass firewall controls.) s
+5 184 M
+( As indicated above, end-point security is assumed during proxy) s
+5 173 M
+( forwarding operations. Failure of end-point security will compromise) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 23]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 24 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( all data passed over proxy forwarding.) s
+5 668 M
+(9.4.3 X11 forwarding) s
+5 646 M
+( Another form of proxy forwarding provided by the ssh connection) s
+5 635 M
+( protocol is the forwarding of the X11 protocol. If end-point) s
+5 624 M
+( security has been compromised, X11 forwarding may allow attacks) s
+5 613 M
+( against the X11 server. Users and administrators should, as a matter) s
+5 602 M
+( of course, use appropriate X11 security mechanisms to prevent) s
+5 591 M
+( unauthorized use of the X11 server. Implementors, administrators and) s
+5 580 M
+( users who wish to further explore the security mechanisms of X11 are) s
+5 569 M
+( invited to read [SCHEIFLER] and analyze previously reported problems) s
+5 558 M
+( with the interactions between SSH forwarding and X11 in CERT) s
+5 547 M
+( vulnerabilities VU#363181 and VU#118892 [CERT].) s
+5 525 M
+( X11 display forwarding with SSH, by itself, is not sufficient to) s
+5 514 M
+( correct well known problems with X11 security [VENEMA]. However, X11) s
+5 503 M
+( display forwarding in SSHv2 \(or other, secure protocols\), combined) s
+5 492 M
+( with actual and pseudo-displays which accept connections only over) s
+5 481 M
+( local IPC mechanisms authorized by permissions or ACLs, does correct) s
+5 470 M
+( many X11 security problems as long as the "none" MAC is not used. It) s
+5 459 M
+( is RECOMMENDED that X11 display implementations default to allowing) s
+5 448 M
+( display opens only over local IPC. It is RECOMMENDED that SSHv2) s
+5 437 M
+( server implementations that support X11 forwarding default to) s
+5 426 M
+( allowing display opens only over local IPC. On single-user systems) s
+5 415 M
+( it might be reasonable to default to allowing local display opens) s
+5 404 M
+( over TCP/IP.) s
+5 382 M
+( Implementors of the X11 forwarding protocol SHOULD implement the) s
+5 371 M
+( magic cookie access checking spoofing mechanism as described in) s
+5 360 M
+( [ssh-connect] as an additional mechanism to prevent unauthorized use) s
+5 349 M
+( of the proxy.) s
+5 327 M
+(Normative References) s
+5 305 M
+( [SSH-ARCH]) s
+5 294 M
+( Ylonen, T., "SSH Protocol Architecture", I-D) s
+5 283 M
+( draft-ietf-architecture-15.txt, Oct 2003.) s
+5 261 M
+( [SSH-TRANS]) s
+5 250 M
+( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
+5 239 M
+( draft-ietf-transport-17.txt, Oct 2003.) s
+5 217 M
+( [SSH-USERAUTH]) s
+5 206 M
+( Ylonen, T., "SSH Authentication Protocol", I-D) s
+5 195 M
+( draft-ietf-userauth-18.txt, Oct 2003.) s
+5 173 M
+( [SSH-CONNECT]) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 24]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (24,25) 13
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 25 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( Ylonen, T., "SSH Connection Protocol", I-D) s
+5 679 M
+( draft-ietf-connect-18.txt, Oct 2003.) s
+5 657 M
+( [SSH-NUMBERS]) s
+5 646 M
+( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
+5 635 M
+( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
+5 624 M
+( 2003.) s
+5 602 M
+( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
+5 591 M
+( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
+5 569 M
+(Informative References) s
+5 547 M
+( [FIPS-186]) s
+5 536 M
+( Federal Information Processing Standards Publication,) s
+5 525 M
+( "FIPS PUB 186, Digital Signature Standard", May 1994.) s
+5 503 M
+( [FIPS-197]) s
+5 492 M
+( National Institue of Standards and Technology, "FIPS 197,) s
+5 481 M
+( Specification for the Advanced Encryption Standard",) s
+5 470 M
+( November 2001.) s
+5 448 M
+( [ANSI T1.523-2001]) s
+5 437 M
+( American National Standards Insitute, Inc., "Telecom) s
+5 426 M
+( Glossary 2000", February 2001.) s
+5 404 M
+( [SCHEIFLER]) s
+5 393 M
+( Scheifler, R., "X Window System : The Complete Reference) s
+5 382 M
+( to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital) s
+5 371 M
+( Press ISBN 1555580882, Feburary 1992.) s
+5 349 M
+( [RFC0854] Postel, J. and J. Reynolds, "Telnet Protocol) s
+5 338 M
+( Specification", STD 8, RFC 854, May 1983.) s
+5 316 M
+( [RFC0894] Hornig, C., "Standard for the transmission of IP datagrams) s
+5 305 M
+( over Ethernet networks", STD 41, RFC 894, April 1984.) s
+5 283 M
+( [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",) s
+5 272 M
+( STD 13, RFC 1034, November 1987.) s
+5 250 M
+( [RFC1134] Perkins, D., "Point-to-Point Protocol: A proposal for) s
+5 239 M
+( multi-protocol transmission of datagrams over) s
+5 228 M
+( Point-to-Point links", RFC 1134, November 1989.) s
+5 206 M
+( [RFC1282] Kantor, B., "BSD Rlogin", RFC 1282, December 1991.) s
+5 184 M
+( [RFC1510] Kohl, J. and B. Neuman, "The Kerberos Network) s
+5 173 M
+( Authentication Service \(V5\)", RFC 1510, September 1993.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 25]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 26 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( [RFC1700] Reynolds, J. and J. Postel, "Assigned Numbers", RFC 1700,) s
+5 679 M
+( October 1994.) s
+5 657 M
+( [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness) s
+5 646 M
+( Recommendations for Security", RFC 1750, December 1994.) s
+5 624 M
+( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
+5 613 M
+( Languages", BCP 47, RFC 3066, January 2001.) s
+5 591 M
+( [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC) s
+5 580 M
+( 1964, June 1996.) s
+5 558 M
+( [RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism) s
+5 547 M
+( \(SPKM\)", RFC 2025, October 1996.) s
+5 525 M
+( [RFC2085] Oehler, M. and R. Glenn, "HMAC-MD5 IP Authentication with) s
+5 514 M
+( Replay Prevention", RFC 2085, February 1997.) s
+5 492 M
+( [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:) s
+5 481 M
+( Keyed-Hashing for Message Authentication", RFC 2104,) s
+5 470 M
+( February 1997.) s
+5 448 M
+( [RFC2246] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A.) s
+5 437 M
+( and P. Kocher, "The TLS Protocol Version 1.0", RFC 2246,) s
+5 426 M
+( January 1999.) s
+5 404 M
+( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
+5 393 M
+( 10646", RFC 2279, January 1998.) s
+5 371 M
+( [RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm and) s
+5 360 M
+( Its Use With IPsec", RFC 2410, November 1998.) s
+5 338 M
+( [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an) s
+5 327 M
+( IANA Considerations Section in RFCs", BCP 26, RFC 2434,) s
+5 316 M
+( October 1998.) s
+5 294 M
+( [RFC2743] Linn, J., "Generic Security Service Application Program) s
+5 283 M
+( Interface Version 2, Update 1", RFC 2743, January 2000.) s
+5 261 M
+( [SCHNEIER]) s
+5 250 M
+( Schneier, B., "Applied Cryptography Second Edition:) s
+5 239 M
+( protocols algorithms and source in code in C", 1996.) s
+5 217 M
+( [KAUFMAN,PERLMAN,SPECINER]) s
+5 206 M
+( Kaufman, C., Perlman, R. and M. Speciner, "Network) s
+5 195 M
+( Security: PRIVATE Communication in a PUBLIC World", 1995.) s
+5 173 M
+( [CERT] CERT Coordination Center, The., "http://www.cert.org/nav/) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 26]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (26,27) 14
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 27 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( index_red.html".) s
+5 668 M
+( [VENEMA] Venema, W., "Murphy's Law and Computer Security",) s
+5 657 M
+( Proceedings of 6th USENIX Security Symposium, San Jose CA) s
+5 646 M
+( http://www.usenix.org/publications/library/proceedings/) s
+5 635 M
+( sec96/venema.html, July 1996.) s
+5 613 M
+( [ROGAWAY] Rogaway, P., "Problems with Proposed IP Cryptography",) s
+5 602 M
+( Unpublished paper http://www.cs.ucdavis.edu/~rogaway/) s
+5 591 M
+( papers/draft-rogaway-ipsec-comments-00.txt, 1996.) s
+5 569 M
+( [DAI] Dai, W., "An attack against SSH2 protocol", Email to the) s
+5 558 M
+( SECSH Working Group [email protected] ftp://) s
+5 547 M
+( ftp.ietf.org/ietf-mail-archive/secsh/2002-02.mail, Feb) s
+5 536 M
+( 2002.) s
+5 514 M
+( [BELLARE,KOHNO,NAMPREMPRE]) s
+5 503 M
+( Bellaire, M., Kohno, T. and C. Namprempre, "Authenticated) s
+5 492 M
+( Encryption in SSH: Fixing the SSH Binary Packet Protocol",) s
+5 481 M
+( , Sept 2002.) s
+5 448 M
+(Authors' Addresses) s
+5 426 M
+( Tatu Ylonen) s
+5 415 M
+( SSH Communications Security Corp) s
+5 404 M
+( Fredrikinkatu 42) s
+5 393 M
+( HELSINKI FIN-00100) s
+5 382 M
+( Finland) s
+5 360 M
+( EMail: [email protected]) s
+5 327 M
+( Darren J. Moffat \(editor\)) s
+5 316 M
+( Sun Microsystems, Inc) s
+5 305 M
+( 17 Network Circle) s
+5 294 M
+( Menlo Park CA 94025) s
+5 283 M
+( USA) s
+5 261 M
+( EMail: [email protected]) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 27]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 28 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+(Intellectual Property Statement) s
+5 668 M
+( The IETF takes no position regarding the validity or scope of any) s
+5 657 M
+( intellectual property or other rights that might be claimed to) s
+5 646 M
+( pertain to the implementation or use of the technology described in) s
+5 635 M
+( this document or the extent to which any license under such rights) s
+5 624 M
+( might or might not be available; neither does it represent that it) s
+5 613 M
+( has made any effort to identify any such rights. Information on the) s
+5 602 M
+( IETF's procedures with respect to rights in standards-track and) s
+5 591 M
+( standards-related documentation can be found in BCP-11. Copies of) s
+5 580 M
+( claims of rights made available for publication and any assurances of) s
+5 569 M
+( licenses to be made available, or the result of an attempt made to) s
+5 558 M
+( obtain a general license or permission for the use of such) s
+5 547 M
+( proprietary rights by implementors or users of this specification can) s
+5 536 M
+( be obtained from the IETF Secretariat.) s
+5 514 M
+( The IETF invites any interested party to bring to its attention any) s
+5 503 M
+( copyrights, patents or patent applications, or other proprietary) s
+5 492 M
+( rights which may cover technology that may be required to practice) s
+5 481 M
+( this standard. Please address the information to the IETF Executive) s
+5 470 M
+( Director.) s
+5 448 M
+( The IETF has been notified of intellectual property rights claimed in) s
+5 437 M
+( regard to some or all of the specification contained in this) s
+5 426 M
+( document. For more information consult the online list of claimed) s
+5 415 M
+( rights.) s
+5 382 M
+(Full Copyright Statement) s
+5 360 M
+( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
+5 338 M
+( This document and translations of it may be copied and furnished to) s
+5 327 M
+( others, and derivative works that comment on or otherwise explain it) s
+5 316 M
+( or assist in its implementation may be prepared, copied, published) s
+5 305 M
+( and distributed, in whole or in part, without restriction of any) s
+5 294 M
+( kind, provided that the above copyright notice and this paragraph are) s
+5 283 M
+( included on all such copies and derivative works. However, this) s
+5 272 M
+( document itself may not be modified in any way, such as by removing) s
+5 261 M
+( the copyright notice or references to the Internet Society or other) s
+5 250 M
+( Internet organizations, except as needed for the purpose of) s
+5 239 M
+( developing Internet standards in which case the procedures for) s
+5 228 M
+( copyrights defined in the Internet Standards process must be) s
+5 217 M
+( followed, or as required to translate it into languages other than) s
+5 206 M
+( English.) s
+5 184 M
+( The limited permissions granted above are perpetual and will not be) s
+5 173 M
+( revoked by the Internet Society or its successors or assignees.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 28]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (28,29) 15
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 29 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Protocol Architecture Oct 2003) s
+5 690 M
+( This document and the information contained herein is provided on an) s
+5 679 M
+( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
+5 668 M
+( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
+5 657 M
+( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
+5 646 M
+( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
+5 635 M
+( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
+5 602 M
+(Acknowledgment) s
+5 580 M
+( Funding for the RFC Editor function is currently provided by the) s
+5 569 M
+( Internet Society.) s
+5 129 M
+(Ylonen & Moffat Expires March 31, 2004 [Page 29]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+showpage
+PStoPSsaved restore
+%%Trailer
+%%Pages: 29
+%%DocumentNeededResources: font Courier-Bold Courier
+%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt
new file mode 100644
index 0000000000..18070e8485
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-architecture-15.txt
@@ -0,0 +1,1624 @@
+
+
+
+Network Working Group T. Ylonen
+Internet-Draft SSH Communications Security Corp
+Expires: March 31, 2004 D. Moffat, Ed.
+ Sun Microsystems, Inc
+ Oct 2003
+
+
+ SSH Protocol Architecture
+ draft-ietf-secsh-architecture-15.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that other
+ groups may also distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on March 31, 2004.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ SSH is a protocol for secure remote login and other secure network
+ services over an insecure network. This document describes the
+ architecture of the SSH protocol, as well as the notation and
+ terminology used in SSH protocol documents. It also discusses the SSH
+ algorithm naming system that allows local extensions. The SSH
+ protocol consists of three major components: The Transport Layer
+ Protocol provides server authentication, confidentiality, and
+ integrity with perfect forward secrecy. The User Authentication
+ Protocol authenticates the client to the server. The Connection
+ Protocol multiplexes the encrypted tunnel into several logical
+ channels. Details of these protocols are described in separate
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 1]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ documents.
+
+Table of Contents
+
+ 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Specification of Requirements . . . . . . . . . . . . . . . 3
+ 4. Architecture . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 4.1 Host Keys . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 4.2 Extensibility . . . . . . . . . . . . . . . . . . . . . . . 5
+ 4.3 Policy Issues . . . . . . . . . . . . . . . . . . . . . . . 5
+ 4.4 Security Properties . . . . . . . . . . . . . . . . . . . . 6
+ 4.5 Packet Size and Overhead . . . . . . . . . . . . . . . . . . 6
+ 4.6 Localization and Character Set Support . . . . . . . . . . . 7
+ 5. Data Type Representations Used in the SSH Protocols . . . . 8
+ 6. Algorithm Naming . . . . . . . . . . . . . . . . . . . . . . 10
+ 7. Message Numbers . . . . . . . . . . . . . . . . . . . . . . 11
+ 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . 11
+ 9. Security Considerations . . . . . . . . . . . . . . . . . . 12
+ 9.1 Pseudo-Random Number Generation . . . . . . . . . . . . . . 12
+ 9.2 Transport . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 9.2.1 Confidentiality . . . . . . . . . . . . . . . . . . . . . . 13
+ 9.2.2 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 16
+ 9.2.3 Replay . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
+ 9.2.4 Man-in-the-middle . . . . . . . . . . . . . . . . . . . . . 17
+ 9.2.5 Denial-of-service . . . . . . . . . . . . . . . . . . . . . 19
+ 9.2.6 Covert Channels . . . . . . . . . . . . . . . . . . . . . . 19
+ 9.2.7 Forward Secrecy . . . . . . . . . . . . . . . . . . . . . . 20
+ 9.3 Authentication Protocol . . . . . . . . . . . . . . . . . . 20
+ 9.3.1 Weak Transport . . . . . . . . . . . . . . . . . . . . . . . 21
+ 9.3.2 Debug messages . . . . . . . . . . . . . . . . . . . . . . . 21
+ 9.3.3 Local security policy . . . . . . . . . . . . . . . . . . . 21
+ 9.3.4 Public key authentication . . . . . . . . . . . . . . . . . 22
+ 9.3.5 Password authentication . . . . . . . . . . . . . . . . . . 22
+ 9.3.6 Host based authentication . . . . . . . . . . . . . . . . . 23
+ 9.4 Connection protocol . . . . . . . . . . . . . . . . . . . . 23
+ 9.4.1 End point security . . . . . . . . . . . . . . . . . . . . . 23
+ 9.4.2 Proxy forwarding . . . . . . . . . . . . . . . . . . . . . . 23
+ 9.4.3 X11 forwarding . . . . . . . . . . . . . . . . . . . . . . . 24
+ Normative References . . . . . . . . . . . . . . . . . . . . 24
+ Informative References . . . . . . . . . . . . . . . . . . . 25
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 27
+ Intellectual Property and Copyright Statements . . . . . . . 28
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 2]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+1. Contributors
+
+ The major original contributors of this document were: Tatu Ylonen,
+ Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
+ Security Corp), and Markku-Juhani O. Saarinen (University of
+ Jyvaskyla)
+
+ The document editor is: [email protected]. Comments on this
+ internet draft should be sent to the IETF SECSH working group,
+ details at: http://ietf.org/html.charters/secsh-charter.html
+
+2. Introduction
+
+ SSH is a protocol for secure remote login and other secure network
+ services over an insecure network. It consists of three major
+ components:
+ o The Transport Layer Protocol [SSH-TRANS] provides server
+ authentication, confidentiality, and integrity. It may optionally
+ also provide compression. The transport layer will typically be
+ run over a TCP/IP connection, but might also be used on top of any
+ other reliable data stream.
+ o The User Authentication Protocol [SSH-USERAUTH] authenticates the
+ client-side user to the server. It runs over the transport layer
+ protocol.
+ o The Connection Protocol [SSH-CONNECT] multiplexes the encrypted
+ tunnel into several logical channels. It runs over the user
+ authentication protocol.
+
+ The client sends a service request once a secure transport layer
+ connection has been established. A second service request is sent
+ after user authentication is complete. This allows new protocols to
+ be defined and coexist with the protocols listed above.
+
+ The connection protocol provides channels that can be used for a wide
+ range of purposes. Standard methods are provided for setting up
+ secure interactive shell sessions and for forwarding ("tunneling")
+ arbitrary TCP/IP ports and X11 connections.
+
+3. Specification of Requirements
+
+ All documents related to the SSH protocols shall use the keywords
+ "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
+ "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" to describe
+ requirements. They are to be interpreted as described in [RFC2119].
+
+4. Architecture
+
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 3]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+4.1 Host Keys
+
+ Each server host SHOULD have a host key. Hosts MAY have multiple
+ host keys using multiple different algorithms. Multiple hosts MAY
+ share the same host key. If a host has keys at all, it MUST have at
+ least one key using each REQUIRED public key algorithm (DSS
+ [FIPS-186]).
+
+ The server host key is used during key exchange to verify that the
+ client is really talking to the correct server. For this to be
+ possible, the client must have a priori knowledge of the server's
+ public host key.
+
+ Two different trust models can be used:
+ o The client has a local database that associates each host name (as
+ typed by the user) with the corresponding public host key. This
+ method requires no centrally administered infrastructure, and no
+ third-party coordination. The downside is that the database of
+ name-to-key associations may become burdensome to maintain.
+ o The host name-to-key association is certified by some trusted
+ certification authority. The client only knows the CA root key,
+ and can verify the validity of all host keys certified by accepted
+ CAs.
+
+ The second alternative eases the maintenance problem, since
+ ideally only a single CA key needs to be securely stored on the
+ client. On the other hand, each host key must be appropriately
+ certified by a central authority before authorization is possible.
+ Also, a lot of trust is placed on the central infrastructure.
+
+ The protocol provides the option that the server name - host key
+ association is not checked when connecting to the host for the first
+ time. This allows communication without prior communication of host
+ keys or certification. The connection still provides protection
+ against passive listening; however, it becomes vulnerable to active
+ man-in-the-middle attacks. Implementations SHOULD NOT normally allow
+ such connections by default, as they pose a potential security
+ problem. However, as there is no widely deployed key infrastructure
+ available on the Internet yet, this option makes the protocol much
+ more usable during the transition time until such an infrastructure
+ emerges, while still providing a much higher level of security than
+ that offered by older solutions (e.g. telnet [RFC-854] and rlogin
+ [RFC-1282]).
+
+ Implementations SHOULD try to make the best effort to check host
+ keys. An example of a possible strategy is to only accept a host key
+ without checking the first time a host is connected, save the key in
+ a local database, and compare against that key on all future
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 4]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ connections to that host.
+
+ Implementations MAY provide additional methods for verifying the
+ correctness of host keys, e.g. a hexadecimal fingerprint derived from
+ the SHA-1 hash of the public key. Such fingerprints can easily be
+ verified by using telephone or other external communication channels.
+
+ All implementations SHOULD provide an option to not accept host keys
+ that cannot be verified.
+
+ We believe that ease of use is critical to end-user acceptance of
+ security solutions, and no improvement in security is gained if the
+ new solutions are not used. Thus, providing the option not to check
+ the server host key is believed to improve the overall security of
+ the Internet, even though it reduces the security of the protocol in
+ configurations where it is allowed.
+
+4.2 Extensibility
+
+ We believe that the protocol will evolve over time, and some
+ organizations will want to use their own encryption, authentication
+ and/or key exchange methods. Central registration of all extensions
+ is cumbersome, especially for experimental or classified features.
+ On the other hand, having no central registration leads to conflicts
+ in method identifiers, making interoperability difficult.
+
+ We have chosen to identify algorithms, methods, formats, and
+ extension protocols with textual names that are of a specific format.
+ DNS names are used to create local namespaces where experimental or
+ classified extensions can be defined without fear of conflicts with
+ other implementations.
+
+ One design goal has been to keep the base protocol as simple as
+ possible, and to require as few algorithms as possible. However, all
+ implementations MUST support a minimal set of algorithms to ensure
+ interoperability (this does not imply that the local policy on all
+ hosts would necessary allow these algorithms). The mandatory
+ algorithms are specified in the relevant protocol documents.
+
+ Additional algorithms, methods, formats, and extension protocols can
+ be defined in separate drafts. See Section Algorithm Naming (Section
+ 6) for more information.
+
+4.3 Policy Issues
+
+ The protocol allows full negotiation of encryption, integrity, key
+ exchange, compression, and public key algorithms and formats.
+ Encryption, integrity, public key, and compression algorithms can be
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 5]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ different for each direction.
+
+ The following policy issues SHOULD be addressed in the configuration
+ mechanisms of each implementation:
+ o Encryption, integrity, and compression algorithms, separately for
+ each direction. The policy MUST specify which is the preferred
+ algorithm (e.g. the first algorithm listed in each category).
+ o Public key algorithms and key exchange method to be used for host
+ authentication. The existence of trusted host keys for different
+ public key algorithms also affects this choice.
+ o The authentication methods that are to be required by the server
+ for each user. The server's policy MAY require multiple
+ authentication for some or all users. The required algorithms MAY
+ depend on the location where the user is trying to log in from.
+ o The operations that the user is allowed to perform using the
+ connection protocol. Some issues are related to security; for
+ example, the policy SHOULD NOT allow the server to start sessions
+ or run commands on the client machine, and MUST NOT allow
+ connections to the authentication agent unless forwarding such
+ connections has been requested. Other issues, such as which TCP/
+ IP ports can be forwarded and by whom, are clearly issues of local
+ policy. Many of these issues may involve traversing or bypassing
+ firewalls, and are interrelated with the local security policy.
+
+4.4 Security Properties
+
+ The primary goal of the SSH protocol is improved security on the
+ Internet. It attempts to do this in a way that is easy to deploy,
+ even at the cost of absolute security.
+ o All encryption, integrity, and public key algorithms used are
+ well-known, well-established algorithms.
+ o All algorithms are used with cryptographically sound key sizes
+ that are believed to provide protection against even the strongest
+ cryptanalytic attacks for decades.
+ o All algorithms are negotiated, and in case some algorithm is
+ broken, it is easy to switch to some other algorithm without
+ modifying the base protocol.
+
+ Specific concessions were made to make wide-spread fast deployment
+ easier. The particular case where this comes up is verifying that
+ the server host key really belongs to the desired host; the protocol
+ allows the verification to be left out (but this is NOT RECOMMENDED).
+ This is believed to significantly improve usability in the short
+ term, until widespread Internet public key infrastructures emerge.
+
+4.5 Packet Size and Overhead
+
+ Some readers will worry about the increase in packet size due to new
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 6]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ headers, padding, and MAC. The minimum packet size is in the order
+ of 28 bytes (depending on negotiated algorithms). The increase is
+ negligible for large packets, but very significant for one-byte
+ packets (telnet-type sessions). There are, however, several factors
+ that make this a non-issue in almost all cases:
+ o The minimum size of a TCP/IP header is 32 bytes. Thus, the
+ increase is actually from 33 to 51 bytes (roughly).
+ o The minimum size of the data field of an Ethernet packet is 46
+ bytes [RFC-894]. Thus, the increase is no more than 5 bytes. When
+ Ethernet headers are considered, the increase is less than 10
+ percent.
+ o The total fraction of telnet-type data in the Internet is
+ negligible, even with increased packet sizes.
+
+ The only environment where the packet size increase is likely to have
+ a significant effect is PPP [RFC-1134] over slow modem lines (PPP
+ compresses the TCP/IP headers, emphasizing the increase in packet
+ size). However, with modern modems, the time needed to transfer is in
+ the order of 2 milliseconds, which is a lot faster than people can
+ type.
+
+ There are also issues related to the maximum packet size. To
+ minimize delays in screen updates, one does not want excessively
+ large packets for interactive sessions. The maximum packet size is
+ negotiated separately for each channel.
+
+4.6 Localization and Character Set Support
+
+ For the most part, the SSH protocols do not directly pass text that
+ would be displayed to the user. However, there are some places where
+ such data might be passed. When applicable, the character set for the
+ data MUST be explicitly specified. In most places, ISO 10646 with
+ UTF-8 encoding is used [RFC-2279]. When applicable, a field is also
+ provided for a language tag [RFC-3066].
+
+ One big issue is the character set of the interactive session. There
+ is no clear solution, as different applications may display data in
+ different formats. Different types of terminal emulation may also be
+ employed in the client, and the character set to be used is
+ effectively determined by the terminal emulation. Thus, no place is
+ provided for directly specifying the character set or encoding for
+ terminal session data. However, the terminal emulation type (e.g.
+ "vt100") is transmitted to the remote site, and it implicitly
+ specifies the character set and encoding. Applications typically use
+ the terminal type to determine what character set they use, or the
+ character set is determined using some external means. The terminal
+ emulation may also allow configuring the default character set. In
+ any case, the character set for the terminal session is considered
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 7]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ primarily a client local issue.
+
+ Internal names used to identify algorithms or protocols are normally
+ never displayed to users, and must be in US-ASCII.
+
+ The client and server user names are inherently constrained by what
+ the server is prepared to accept. They might, however, occasionally
+ be displayed in logs, reports, etc. They MUST be encoded using ISO
+ 10646 UTF-8, but other encodings may be required in some cases. It
+ is up to the server to decide how to map user names to accepted user
+ names. Straight bit-wise binary comparison is RECOMMENDED.
+
+ For localization purposes, the protocol attempts to minimize the
+ number of textual messages transmitted. When present, such messages
+ typically relate to errors, debugging information, or some externally
+ configured data. For data that is normally displayed, it SHOULD be
+ possible to fetch a localized message instead of the transmitted
+ message by using a numerical code. The remaining messages SHOULD be
+ configurable.
+
+5. Data Type Representations Used in the SSH Protocols
+ byte
+
+ A byte represents an arbitrary 8-bit value (octet) [RFC-1700].
+ Fixed length data is sometimes represented as an array of bytes,
+ written byte[n], where n is the number of bytes in the array.
+
+ boolean
+
+ A boolean value is stored as a single byte. The value 0
+ represents FALSE, and the value 1 represents TRUE. All non-zero
+ values MUST be interpreted as TRUE; however, applications MUST NOT
+ store values other than 0 and 1.
+
+ uint32
+
+ Represents a 32-bit unsigned integer. Stored as four bytes in the
+ order of decreasing significance (network byte order). For
+ example, the value 699921578 (0x29b7f4aa) is stored as 29 b7 f4
+ aa.
+
+ uint64
+
+ Represents a 64-bit unsigned integer. Stored as eight bytes in
+ the order of decreasing significance (network byte order).
+
+
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 8]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ string
+
+ Arbitrary length binary string. Strings are allowed to contain
+ arbitrary binary data, including null characters and 8-bit
+ characters. They are stored as a uint32 containing its length
+ (number of bytes that follow) and zero (= empty string) or more
+ bytes that are the value of the string. Terminating null
+ characters are not used.
+
+ Strings are also used to store text. In that case, US-ASCII is
+ used for internal names, and ISO-10646 UTF-8 for text that might
+ be displayed to the user. The terminating null character SHOULD
+ NOT normally be stored in the string.
+
+ For example, the US-ASCII string "testing" is represented as 00 00
+ 00 07 t e s t i n g. The UTF8 mapping does not alter the encoding
+ of US-ASCII characters.
+
+ mpint
+
+ Represents multiple precision integers in two's complement format,
+ stored as a string, 8 bits per byte, MSB first. Negative numbers
+ have the value 1 as the most significant bit of the first byte of
+ the data partition. If the most significant bit would be set for a
+ positive number, the number MUST be preceded by a zero byte.
+ Unnecessary leading bytes with the value 0 or 255 MUST NOT be
+ included. The value zero MUST be stored as a string with zero
+ bytes of data.
+
+ By convention, a number that is used in modular computations in
+ Z_n SHOULD be represented in the range 0 <= x < n.
+
+ Examples:
+ value (hex) representation (hex)
+ ---------------------------------------------------------------
+ 0 00 00 00 00
+ 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7
+ 80 00 00 00 02 00 80
+ -1234 00 00 00 02 ed cc
+ -deadbeef 00 00 00 05 ff 21 52 41 11
+
+
+
+ name-list
+
+ A string containing a comma separated list of names. A name list
+ is represented as a uint32 containing its length (number of bytes
+ that follow) followed by a comma-separated list of zero or more
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 9]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ names. A name MUST be non-zero length, and it MUST NOT contain a
+ comma (','). Context may impose additional restrictions on the
+ names; for example, the names in a list may have to be valid
+ algorithm identifier (see Algorithm Naming below), or [RFC-3066]
+ language tags. The order of the names in a list may or may not be
+ significant, also depending on the context where the list is is
+ used. Terminating NUL characters are not used, neither for the
+ individual names, nor for the list as a whole.
+
+ Examples:
+ value representation (hex)
+ ---------------------------------------
+ (), the empty list 00 00 00 00
+ ("zlib") 00 00 00 04 7a 6c 69 62
+ ("zlib", "none") 00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65
+
+
+
+
+6. Algorithm Naming
+
+ The SSH protocols refer to particular hash, encryption, integrity,
+ compression, and key exchange algorithms or protocols by names.
+ There are some standard algorithms that all implementations MUST
+ support. There are also algorithms that are defined in the protocol
+ specification but are OPTIONAL. Furthermore, it is expected that
+ some organizations will want to use their own algorithms.
+
+ In this protocol, all algorithm identifiers MUST be printable
+ US-ASCII non-empty strings no longer than 64 characters. Names MUST
+ be case-sensitive.
+
+ There are two formats for algorithm names:
+ o Names that do not contain an at-sign (@) are reserved to be
+ assigned by IETF consensus (RFCs). Examples include `3des-cbc',
+ `sha-1', `hmac-sha1', and `zlib' (the quotes are not part of the
+ name). Names of this format MUST NOT be used without first
+ registering them. Registered names MUST NOT contain an at-sign
+ (@) or a comma (,).
+ o Anyone can define additional algorithms by using names in the
+ format name@domainname, e.g. "[email protected]". The
+ format of the part preceding the at sign is not specified; it MUST
+ consist of US-ASCII characters except at-sign and comma. The part
+ following the at-sign MUST be a valid fully qualified internet
+ domain name [RFC-1034] controlled by the person or organization
+ defining the name. It is up to each domain how it manages its
+ local namespace.
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 10]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+7. Message Numbers
+
+ SSH packets have message numbers in the range 1 to 255. These numbers
+ have been allocated as follows:
+
+
+ Transport layer protocol:
+
+ 1 to 19 Transport layer generic (e.g. disconnect, ignore, debug,
+ etc.)
+ 20 to 29 Algorithm negotiation
+ 30 to 49 Key exchange method specific (numbers can be reused for
+ different authentication methods)
+
+ User authentication protocol:
+
+ 50 to 59 User authentication generic
+ 60 to 79 User authentication method specific (numbers can be
+ reused for different authentication methods)
+
+ Connection protocol:
+
+ 80 to 89 Connection protocol generic
+ 90 to 127 Channel related messages
+
+ Reserved for client protocols:
+
+ 128 to 191 Reserved
+
+ Local extensions:
+
+ 192 to 255 Local extensions
+
+
+
+8. IANA Considerations
+
+ The initial state of the IANA registry is detailed in [SSH-NUMBERS].
+
+ Allocation of the following types of names in the SSH protocols is
+ assigned by IETF consensus:
+ o SSH encryption algorithm names,
+ o SSH MAC algorithm names,
+ o SSH public key algorithm names (public key algorithm also implies
+ encoding and signature/encryption capability),
+ o SSH key exchange method names, and
+ o SSH protocol (service) names.
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 11]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ These names MUST be printable US-ASCII strings, and MUST NOT contain
+ the characters at-sign ('@'), comma (','), or whitespace or control
+ characters (ASCII codes 32 or less). Names are case-sensitive, and
+ MUST NOT be longer than 64 characters.
+
+ Names with the at-sign ('@') in them are allocated by the owner of
+ DNS name after the at-sign (hierarchical allocation in [RFC-2343]),
+ otherwise the same restrictions as above.
+
+ Each category of names listed above has a separate namespace.
+ However, using the same name in multiple categories SHOULD be avoided
+ to minimize confusion.
+
+ Message numbers (see Section Message Numbers (Section 7)) in the
+ range of 0..191 are allocated via IETF consensus; message numbers in
+ the 192..255 range (the "Local extensions" set) are reserved for
+ private use.
+
+9. Security Considerations
+
+ In order to make the entire body of Security Considerations more
+ accessible, Security Considerations for the transport,
+ authentication, and connection documents have been gathered here.
+
+ The transport protocol [1] provides a confidential channel over an
+ insecure network. It performs server host authentication, key
+ exchange, encryption, and integrity protection. It also derives a
+ unique session id that may be used by higher-level protocols.
+
+ The authentication protocol [2] provides a suite of mechanisms which
+ can be used to authenticate the client user to the server.
+ Individual mechanisms specified in the in authentication protocol use
+ the session id provided by the transport protocol and/or depend on
+ the security and integrity guarantees of the transport protocol.
+
+ The connection protocol [3] specifies a mechanism to multiplex
+ multiple streams [channels] of data over the confidential and
+ authenticated transport. It also specifies channels for accessing an
+ interactive shell, for 'proxy-forwarding' various external protocols
+ over the secure transport (including arbitrary TCP/IP protocols), and
+ for accessing secure 'subsystems' on the server host.
+
+9.1 Pseudo-Random Number Generation
+
+ This protocol binds each session key to the session by including
+ random, session specific data in the hash used to produce session
+ keys. Special care should be taken to ensure that all of the random
+ numbers are of good quality. If the random data here (e.g., DH
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 12]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ parameters) are pseudo-random then the pseudo-random number generator
+ should be cryptographically secure (i.e., its next output not easily
+ guessed even when knowing all previous outputs) and, furthermore,
+ proper entropy needs to be added to the pseudo-random number
+ generator. RFC 1750 [1750] offers suggestions for sources of random
+ numbers and entropy. Implementors should note the importance of
+ entropy and the well-meant, anecdotal warning about the difficulty in
+ properly implementing pseudo-random number generating functions.
+
+ The amount of entropy available to a given client or server may
+ sometimes be less than what is required. In this case one must
+ either resort to pseudo-random number generation regardless of
+ insufficient entropy or refuse to run the protocol. The latter is
+ preferable.
+
+9.2 Transport
+
+9.2.1 Confidentiality
+
+ It is beyond the scope of this document and the Secure Shell Working
+ Group to analyze or recommend specific ciphers other than the ones
+ which have been established and accepted within the industry. At the
+ time of this writing, ciphers commonly in use include 3DES, ARCFOUR,
+ twofish, serpent and blowfish. AES has been accepted by The
+ published as a US Federal Information Processing Standards [FIPS-197]
+ and the cryptographic community as being acceptable for this purpose
+ as well has accepted AES. As always, implementors and users should
+ check current literature to ensure that no recent vulnerabilities
+ have been found in ciphers used within products. Implementors should
+ also check to see which ciphers are considered to be relatively
+ stronger than others and should recommend their use to users over
+ relatively weaker ciphers. It would be considered good form for an
+ implementation to politely and unobtrusively notify a user that a
+ stronger cipher is available and should be used when a weaker one is
+ actively chosen.
+
+ The "none" cipher is provided for debugging and SHOULD NOT be used
+ except for that purpose. It's cryptographic properties are
+ sufficiently described in RFC 2410, which will show that its use does
+ not meet the intent of this protocol.
+
+ The relative merits of these and other ciphers may also be found in
+ current literature. Two references that may provide information on
+ the subject are [SCHNEIER] and [KAUFMAN,PERLMAN,SPECINER]. Both of
+ these describe the CBC mode of operation of certain ciphers and the
+ weakness of this scheme. Essentially, this mode is theoretically
+ vulnerable to chosen cipher-text attacks because of the high
+ predictability of the start of packet sequence. However, this attack
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 13]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ is still deemed difficult and not considered fully practicable
+ especially if relatively longer block sizes are used.
+
+ Additionally, another CBC mode attack may be mitigated through the
+ insertion of packets containing SSH_MSG_IGNORE. Without this
+ technique, a specific attack may be successful. For this attack
+ (commonly known as the Rogaway attack
+ [ROGAWAY],[DAI],[BELLARE,KOHNO,NAMPREMPRE]) to work, the attacker
+ would need to know the IV of the next block that is going to be
+ encrypted. In CBC mode that is the output of the encryption of the
+ previous block. If the attacker does not have any way to see the
+ packet yet (i.e it is in the internal buffers of the ssh
+ implementation or even in the kernel) then this attack will not work.
+ If the last packet has been sent out to the network (i.e the attacker
+ has access to it) then he can use the attack.
+
+ In the optimal case an implementor would need to add an extra packet
+ only if the packet has been sent out onto the network and there are
+ no other packets waiting for transmission. Implementors may wish to
+ check to see if there are any unsent packets awaiting transmission,
+ but unfortunately it is not normally easy to obtain this information
+ from the kernel or buffers. If there are not, then a packet
+ containing SSH_MSG_IGNORE SHOULD be sent. If a new packet is added
+ to the stream every time the attacker knows the IV that is supposed
+ to be used for the next packet, then the attacker will not be able to
+ guess the correct IV, thus the attack will never be successfull.
+
+ As an example, consider the following case:
+
+
+ Client Server
+ ------ ------
+ TCP(seq=x, len=500) ->
+ contains Record 1
+
+ [500 ms passes, no ACK]
+
+ TCP(seq=x, len=1000) ->
+ contains Records 1,2
+
+ ACK
+
+
+ 1. The Nagle algorithm + TCP retransmits mean that the two records
+ get coalesced into a single TCP segment
+ 2. Record 2 is *not* at the beginning of the TCP segment and never
+ will be, since it gets ACKed.
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 14]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ 3. Yet, the attack is possible because Record 1 has already been
+ seen.
+
+ As this example indicates, it's totally unsafe to use the existence
+ of unflushed data in the TCP buffers proper as a guide to whether you
+ need an empty packet, since when you do the second write(), the
+ buffers will contain the un-ACKed Record 1.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 15]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ On the other hand, it's perfectly safe to have the following
+ situation:
+
+
+ Client Server
+ ------ ------
+ TCP(seq=x, len=500) ->
+ contains SSH_MSG_IGNORE
+
+ TCP(seq=y, len=500) ->
+ contains Data
+
+ Provided that the IV for second SSH Record is fixed after the data for
+ the Data packet is determined -i.e. you do:
+ read from user
+ encrypt null packet
+ encrypt data packet
+
+
+9.2.2 Data Integrity
+
+ This protocol does allow the Data Integrity mechanism to be disabled.
+ Implementors SHOULD be wary of exposing this feature for any purpose
+ other than debugging. Users and administrators SHOULD be explicitly
+ warned anytime the "none" MAC is enabled.
+
+ So long as the "none" MAC is not used, this protocol provides data
+ integrity.
+
+ Because MACs use a 32 bit sequence number, they might start to leak
+ information after 2**32 packets have been sent. However, following
+ the rekeying recommendations should prevent this attack. The
+ transport protocol [1] recommends rekeying after one gigabyte of
+ data, and the smallest possible packet is 16 bytes. Therefore,
+ rekeying SHOULD happen after 2**28 packets at the very most.
+
+9.2.3 Replay
+
+ The use of a MAC other than 'none' provides integrity and
+ authentication. In addition, the transport protocol provides a
+ unique session identifier (bound in part to pseudo-random data that
+ is part of the algorithm and key exchange process) that can be used
+ by higher level protocols to bind data to a given session and prevent
+ replay of data from prior sessions. For example, the authentication
+ protocol uses this to prevent replay of signatures from previous
+ sessions. Because public key authentication exchanges are
+ cryptographically bound to the session (i.e., to the initial key
+ exchange) they cannot be successfully replayed in other sessions.
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 16]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ Note that the session ID can be made public without harming the
+ security of the protocol.
+
+ If two session happen to have the same session ID [hash of key
+ exchanges] then packets from one can be replayed against the other.
+ It must be stressed that the chances of such an occurrence are,
+ needless to say, minimal when using modern cryptographic methods.
+ This is all the more so true when specifying larger hash function
+ outputs and DH parameters.
+
+ Replay detection using monotonically increasing sequence numbers as
+ input to the MAC, or HMAC in some cases, is described in [RFC2085] />
+ [RFC2246], [RFC2743], [RFC1964], [RFC2025], and [RFC1510]. The
+ underlying construct is discussed in [RFC2104]. Essentially a
+ different sequence number in each packet ensures that at least this
+ one input to the MAC function will be unique and will provide a
+ nonrecurring MAC output that is not predictable to an attacker. If
+ the session stays active long enough, however, this sequence number
+ will wrap. This event may provide an attacker an opportunity to
+ replay a previously recorded packet with an identical sequence number
+ but only if the peers have not rekeyed since the transmission of the
+ first packet with that sequence number. If the peers have rekeyed,
+ then the replay will be detected as the MAC check will fail. For
+ this reason, it must be emphasized that peers MUST rekey before a
+ wrap of the sequence numbers. Naturally, if an attacker does attempt
+ to replay a captured packet before the peers have rekeyed, then the
+ receiver of the duplicate packet will not be able to validate the MAC
+ and it will be discarded. The reason that the MAC will fail is
+ because the receiver will formulate a MAC based upon the packet
+ contents, the shared secret, and the expected sequence number. Since
+ the replayed packet will not be using that expected sequence number
+ (the sequence number of the replayed packet will have already been
+ passed by the receiver) then the calculated MAC will not match the
+ MAC received with the packet.
+
+9.2.4 Man-in-the-middle
+
+ This protocol makes no assumptions nor provisions for an
+ infrastructure or means for distributing the public keys of hosts. It
+ is expected that this protocol will sometimes be used without first
+ verifying the association between the server host key and the server
+ host name. Such usage is vulnerable to man-in-the-middle attacks.
+ This section describes this and encourages administrators and users
+ to understand the importance of verifying this association before any
+ session is initiated.
+
+ There are three cases of man-in-the-middle attacks to consider. The
+ first is where an attacker places a device between the client and the
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 17]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ server before the session is initiated. In this case, the attack
+ device is trying to mimic the legitimate server and will offer its
+ public key to the client when the client initiates a session. If it
+ were to offer the public key of the server, then it would not be able
+ to decrypt or sign the transmissions between the legitimate server
+ and the client unless it also had access to the private-key of the
+ host. The attack device will also, simultaneously to this, initiate
+ a session to the legitimate server masquerading itself as the client.
+ If the public key of the server had been securely distributed to the
+ client prior to that session initiation, the key offered to the
+ client by the attack device will not match the key stored on the
+ client. In that case, the user SHOULD be given a warning that the
+ offered host key does not match the host key cached on the client.
+ As described in Section 3.1 of [ARCH], the user may be free to accept
+ the new key and continue the session. It is RECOMMENDED that the
+ warning provide sufficient information to the user of the client
+ device so they may make an informed decision. If the user chooses to
+ continue the session with the stored public-key of the server (not
+ the public-key offered at the start of the session), then the session
+ specific data between the attacker and server will be different
+ between the client-to-attacker session and the attacker-to-server
+ sessions due to the randomness discussed above. From this, the
+ attacker will not be able to make this attack work since the attacker
+ will not be able to correctly sign packets containing this session
+ specific data from the server since he does not have the private key
+ of that server.
+
+ The second case that should be considered is similar to the first
+ case in that it also happens at the time of connection but this case
+ points out the need for the secure distribution of server public
+ keys. If the server public keys are not securely distributed then
+ the client cannot know if it is talking to the intended server. An
+ attacker may use social engineering techniques to pass off server
+ keys to unsuspecting users and may then place a man-in-the-middle
+ attack device between the legitimate server and the clients. If this
+ is allowed to happen then the clients will form client-to-attacker
+ sessions and the attacker will form attacker-to-server sessions and
+ will be able to monitor and manipulate all of the traffic between the
+ clients and the legitimate servers. Server administrators are
+ encouraged to make host key fingerprints available for checking by
+ some means whose security does not rely on the integrity of the
+ actual host keys. Possible mechanisms are discussed in Section 3.1
+ of [SSH-ARCH] and may also include secured Web pages, physical pieces
+ of paper, etc. Implementors SHOULD provide recommendations on how
+ best to do this with their implementation. Because the protocol is
+ extensible, future extensions to the protocol may provide better
+ mechanisms for dealing with the need to know the server's host key
+ before connecting. For example, making the host key fingerprint
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 18]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ available through a secure DNS lookup, or using kerberos over gssapi
+ during key exchange to authenticate the server are possibilities.
+
+ In the third man-in-the-middle case, attackers may attempt to
+ manipulate packets in transit between peers after the session has
+ been established. As described in the Replay part of this section, a
+ successful attack of this nature is very improbable. As in the
+ Replay section, this reasoning does assume that the MAC is secure and
+ that it is infeasible to construct inputs to a MAC algorithm to give
+ a known output. This is discussed in much greater detail in Section
+ 6 of RFC 2104. If the MAC algorithm has a vulnerability or is weak
+ enough, then the attacker may be able to specify certain inputs to
+ yield a known MAC. With that they may be able to alter the contents
+ of a packet in transit. Alternatively the attacker may be able to
+ exploit the algorithm vulnerability or weakness to find the shared
+ secret by reviewing the MACs from captured packets. In either of
+ those cases, an attacker could construct a packet or packets that
+ could be inserted into an SSH stream. To prevent that, implementors
+ are encouraged to utilize commonly accepted MAC algorithms and
+ administrators are encouraged to watch current literature and
+ discussions of cryptography to ensure that they are not using a MAC
+ algorithm that has a recently found vulnerability or weakness.
+
+ In summary, the use of this protocol without a reliable association
+ of the binding between a host and its host keys is inherently
+ insecure and is NOT RECOMMENDED. It may however be necessary in
+ non-security critical environments, and will still provide protection
+ against passive attacks. Implementors of protocols and applications
+ running on top of this protocol should keep this possibility in mind.
+
+9.2.5 Denial-of-service
+
+ This protocol is designed to be used over a reliable transport. If
+ transmission errors or message manipulation occur, the connection is
+ closed. The connection SHOULD be re-established if this occurs.
+ Denial of service attacks of this type ("wire cutter") are almost
+ impossible to avoid.
+
+ In addition, this protocol is vulnerable to Denial of Service attacks
+ because an attacker can force the server to go through the CPU and
+ memory intensive tasks of connection setup and key exchange without
+ authenticating. Implementors SHOULD provide features that make this
+ more difficult. For example, only allowing connections from a subset
+ of IPs known to have valid users.
+
+9.2.6 Covert Channels
+
+ The protocol was not designed to eliminate covert channels. For
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 19]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ example, the padding, SSH_MSG_IGNORE messages, and several other
+ places in the protocol can be used to pass covert information, and
+ the recipient has no reliable way to verify whether such information
+ is being sent.
+
+9.2.7 Forward Secrecy
+
+ It should be noted that the Diffie-Hellman key exchanges may provide
+ perfect forward secrecy (PFS). PFS is essentially defined as the
+ cryptographic property of a key-establishment protocol in which the
+ compromise of a session key or long-term private key after a given
+ session does not cause the compromise of any earlier session. [ANSI
+ T1.523-2001] SSHv2 sessions resulting from a key exchange using
+ diffie-hellman-group1-sha1 are secure even if private keying/
+ authentication material is later revealed, but not if the session
+ keys are revealed. So, given this definition of PFS, SSHv2 does have
+ PFS. It is hoped that all other key exchange mechanisms proposed and
+ used in the future will also provide PFS. This property is not
+ commuted to any of the applications or protocols using SSH as a
+ transport however. The transport layer of SSH provides
+ confidentiality for password authentication and other methods that
+ rely on secret data.
+
+ Of course, if the DH private parameters for the client and server are
+ revealed then the session key is revealed, but these items can be
+ thrown away after the key exchange completes. It's worth pointing
+ out that these items should not be allowed to end up on swap space
+ and that they should be erased from memory as soon as the key
+ exchange completes.
+
+9.3 Authentication Protocol
+
+ The purpose of this protocol is to perform client user
+ authentication. It assumes that this run over a secure transport
+ layer protocol, which has already authenticated the server machine,
+ established an encrypted communications channel, and computed a
+ unique session identifier for this session.
+
+ Several authentication methods with different security
+ characteristics are allowed. It is up to the server's local policy
+ to decide which methods (or combinations of methods) it is willing to
+ accept for each user. Authentication is no stronger than the weakest
+ combination allowed.
+
+ The server may go into a "sleep" period after repeated unsuccessful
+ authentication attempts to make key search more difficult for
+ attackers. Care should be taken so that this doesn't become a
+ self-denial of service vector.
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 20]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+9.3.1 Weak Transport
+
+ If the transport layer does not provide confidentiality,
+ authentication methods that rely on secret data SHOULD be disabled.
+ If it does not provide strong integrity protection, requests to
+ change authentication data (e.g. a password change) SHOULD be
+ disabled to prevent an attacker from modifying the ciphertext
+ without being noticed, or rendering the new authentication data
+ unusable (denial of service).
+
+ The assumption as stated above that the Authentication Protocol only
+ run over a secure transport that has previously authenticated the
+ server is very important to note. People deploying SSH are reminded
+ of the consequences of man-in-the-middle attacks if the client does
+ not have a very strong a priori association of the server with the
+ host key of that server. Specifically for the case of the
+ Authentication Protocol the client may form a session to a
+ man-in-the-middle attack device and divulge user credentials such as
+ their username and password. Even in the cases of authentication
+ where no user credentials are divulged, an attacker may still gain
+ information they shouldn't have by capturing key-strokes in much the
+ same way that a honeypot works.
+
+9.3.2 Debug messages
+
+ Special care should be taken when designing debug messages. These
+ messages may reveal surprising amounts of information about the host
+ if not properly designed. Debug messages can be disabled (during
+ user authentication phase) if high security is required.
+ Administrators of host machines should make all attempts to
+ compartmentalize all event notification messages and protect them
+ from unwarranted observation. Developers should be aware of the
+ sensitive nature of some of the normal event messages and debug
+ messages and may want to provide guidance to administrators on ways
+ to keep this information away from unauthorized people. Developers
+ should consider minimizing the amount of sensitive information
+ obtainable by users during the authentication phase in accordance
+ with the local policies. For this reason, it is RECOMMENDED that
+ debug messages be initially disabled at the time of deployment and
+ require an active decision by an administrator to allow them to be
+ enabled. It is also RECOMMENDED that a message expressing this
+ concern be presented to the administrator of a system when the action
+ is taken to enable debugging messages.
+
+9.3.3 Local security policy
+
+ Implementer MUST ensure that the credentials provided validate the
+ professed user and also MUST ensure that the local policy of the
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 21]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ server permits the user the access requested. In particular, because
+ of the flexible nature of the SSH connection protocol, it may not be
+ possible to determine the local security policy, if any, that should
+ apply at the time of authentication because the kind of service being
+ requested is not clear at that instant. For example, local policy
+ might allow a user to access files on the server, but not start an
+ interactive shell. However, during the authentication protocol, it is
+ not known whether the user will be accessing files or attempting to
+ use an interactive shell, or even both. In any event, where local
+ security policy for the server host exists, it MUST be applied and
+ enforced correctly.
+
+ Implementors are encouraged to provide a default local policy and
+ make its parameters known to administrators and users. At the
+ discretion of the implementors, this default policy may be along the
+ lines of 'anything goes' where there are no restrictions placed upon
+ users, or it may be along the lines of 'excessively restrictive' in
+ which case the administrators will have to actively make changes to
+ this policy to meet their needs. Alternatively, it may be some
+ attempt at providing something practical and immediately useful to
+ the administrators of the system so they don't have to put in much
+ effort to get SSH working. Whatever choice is made MUST be applied
+ and enforced as required above.
+
+9.3.4 Public key authentication
+
+ The use of public-key authentication assumes that the client host has
+ not been compromised. It also assumes that the private-key of the
+ server host has not been compromised.
+
+ This risk can be mitigated by the use of passphrases on private keys;
+ however, this is not an enforceable policy. The use of smartcards,
+ or other technology to make passphrases an enforceable policy is
+ suggested.
+
+ The server could require both password and public-key authentication,
+ however, this requires the client to expose its password to the
+ server (see section on password authentication below.)
+
+9.3.5 Password authentication
+
+ The password mechanism as specified in the authentication protocol
+ assumes that the server has not been compromised. If the server has
+ been compromised, using password authentication will reveal a valid
+ username / password combination to the attacker, which may lead to
+ further compromises.
+
+ This vulnerability can be mitigated by using an alternative form of
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 22]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ authentication. For example, public-key authentication makes no
+ assumptions about security on the server.
+
+9.3.6 Host based authentication
+
+ Host based authentication assumes that the client has not been
+ compromised. There are no mitigating strategies, other than to use
+ host based authentication in combination with another authentication
+ method.
+
+9.4 Connection protocol
+
+9.4.1 End point security
+
+ End point security is assumed by the connection protocol. If the
+ server has been compromised, any terminal sessions, port forwarding,
+ or systems accessed on the host are compromised. There are no
+ mitigating factors for this.
+
+ If the client end point has been compromised, and the server fails to
+ stop the attacker at the authentication protocol, all services
+ exposed (either as subsystems or through forwarding) will be
+ vulnerable to attack. Implementors SHOULD provide mechanisms for
+ administrators to control which services are exposed to limit the
+ vulnerability of other services.
+
+ These controls might include controlling which machines and ports can
+ be target in 'port-forwarding' operations, which users are allowed to
+ use interactive shell facilities, or which users are allowed to use
+ exposed subsystems.
+
+9.4.2 Proxy forwarding
+
+ The SSH connection protocol allows for proxy forwarding of other
+ protocols such as SNMP, POP3, and HTTP. This may be a concern for
+ network administrators who wish to control the access of certain
+ applications by users located outside of their physical location.
+ Essentially, the forwarding of these protocols may violate site
+ specific security policies as they may be undetectably tunneled
+ through a firewall. Implementors SHOULD provide an administrative
+ mechanism to control the proxy forwarding functionality so that site
+ specific security policies may be upheld.
+
+ In addition, a reverse proxy forwarding functionality is available,
+ which again can be used to bypass firewall controls.
+
+ As indicated above, end-point security is assumed during proxy
+ forwarding operations. Failure of end-point security will compromise
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 23]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ all data passed over proxy forwarding.
+
+9.4.3 X11 forwarding
+
+ Another form of proxy forwarding provided by the ssh connection
+ protocol is the forwarding of the X11 protocol. If end-point
+ security has been compromised, X11 forwarding may allow attacks
+ against the X11 server. Users and administrators should, as a matter
+ of course, use appropriate X11 security mechanisms to prevent
+ unauthorized use of the X11 server. Implementors, administrators and
+ users who wish to further explore the security mechanisms of X11 are
+ invited to read [SCHEIFLER] and analyze previously reported problems
+ with the interactions between SSH forwarding and X11 in CERT
+ vulnerabilities VU#363181 and VU#118892 [CERT].
+
+ X11 display forwarding with SSH, by itself, is not sufficient to
+ correct well known problems with X11 security [VENEMA]. However, X11
+ display forwarding in SSHv2 (or other, secure protocols), combined
+ with actual and pseudo-displays which accept connections only over
+ local IPC mechanisms authorized by permissions or ACLs, does correct
+ many X11 security problems as long as the "none" MAC is not used. It
+ is RECOMMENDED that X11 display implementations default to allowing
+ display opens only over local IPC. It is RECOMMENDED that SSHv2
+ server implementations that support X11 forwarding default to
+ allowing display opens only over local IPC. On single-user systems
+ it might be reasonable to default to allowing local display opens
+ over TCP/IP.
+
+ Implementors of the X11 forwarding protocol SHOULD implement the
+ magic cookie access checking spoofing mechanism as described in
+ [ssh-connect] as an additional mechanism to prevent unauthorized use
+ of the proxy.
+
+Normative References
+
+ [SSH-ARCH]
+ Ylonen, T., "SSH Protocol Architecture", I-D
+ draft-ietf-architecture-15.txt, Oct 2003.
+
+ [SSH-TRANS]
+ Ylonen, T., "SSH Transport Layer Protocol", I-D
+ draft-ietf-transport-17.txt, Oct 2003.
+
+ [SSH-USERAUTH]
+ Ylonen, T., "SSH Authentication Protocol", I-D
+ draft-ietf-userauth-18.txt, Oct 2003.
+
+ [SSH-CONNECT]
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 24]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ Ylonen, T., "SSH Connection Protocol", I-D
+ draft-ietf-connect-18.txt, Oct 2003.
+
+ [SSH-NUMBERS]
+ Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
+ Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
+ 2003.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+Informative References
+
+ [FIPS-186]
+ Federal Information Processing Standards Publication,
+ "FIPS PUB 186, Digital Signature Standard", May 1994.
+
+ [FIPS-197]
+ National Institue of Standards and Technology, "FIPS 197,
+ Specification for the Advanced Encryption Standard",
+ November 2001.
+
+ [ANSI T1.523-2001]
+ American National Standards Insitute, Inc., "Telecom
+ Glossary 2000", February 2001.
+
+ [SCHEIFLER]
+ Scheifler, R., "X Window System : The Complete Reference
+ to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital
+ Press ISBN 1555580882, Feburary 1992.
+
+ [RFC0854] Postel, J. and J. Reynolds, "Telnet Protocol
+ Specification", STD 8, RFC 854, May 1983.
+
+ [RFC0894] Hornig, C., "Standard for the transmission of IP datagrams
+ over Ethernet networks", STD 41, RFC 894, April 1984.
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1134] Perkins, D., "Point-to-Point Protocol: A proposal for
+ multi-protocol transmission of datagrams over
+ Point-to-Point links", RFC 1134, November 1989.
+
+ [RFC1282] Kantor, B., "BSD Rlogin", RFC 1282, December 1991.
+
+ [RFC1510] Kohl, J. and B. Neuman, "The Kerberos Network
+ Authentication Service (V5)", RFC 1510, September 1993.
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 25]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ [RFC1700] Reynolds, J. and J. Postel, "Assigned Numbers", RFC 1700,
+ October 1994.
+
+ [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
+ Recommendations for Security", RFC 1750, December 1994.
+
+ [RFC3066] Alvestrand, H., "Tags for the Identification of
+ Languages", BCP 47, RFC 3066, January 2001.
+
+ [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC
+ 1964, June 1996.
+
+ [RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism
+ (SPKM)", RFC 2025, October 1996.
+
+ [RFC2085] Oehler, M. and R. Glenn, "HMAC-MD5 IP Authentication with
+ Replay Prevention", RFC 2085, February 1997.
+
+ [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:
+ Keyed-Hashing for Message Authentication", RFC 2104,
+ February 1997.
+
+ [RFC2246] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A.
+ and P. Kocher, "The TLS Protocol Version 1.0", RFC 2246,
+ January 1999.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+ [RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm and
+ Its Use With IPsec", RFC 2410, November 1998.
+
+ [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [RFC2743] Linn, J., "Generic Security Service Application Program
+ Interface Version 2, Update 1", RFC 2743, January 2000.
+
+ [SCHNEIER]
+ Schneier, B., "Applied Cryptography Second Edition:
+ protocols algorithms and source in code in C", 1996.
+
+ [KAUFMAN,PERLMAN,SPECINER]
+ Kaufman, C., Perlman, R. and M. Speciner, "Network
+ Security: PRIVATE Communication in a PUBLIC World", 1995.
+
+ [CERT] CERT Coordination Center, The., "http://www.cert.org/nav/
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 26]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ index_red.html".
+
+ [VENEMA] Venema, W., "Murphy's Law and Computer Security",
+ Proceedings of 6th USENIX Security Symposium, San Jose CA
+ http://www.usenix.org/publications/library/proceedings/
+ sec96/venema.html, July 1996.
+
+ [ROGAWAY] Rogaway, P., "Problems with Proposed IP Cryptography",
+ Unpublished paper http://www.cs.ucdavis.edu/~rogaway/
+ papers/draft-rogaway-ipsec-comments-00.txt, 1996.
+
+ [DAI] Dai, W., "An attack against SSH2 protocol", Email to the
+ SECSH Working Group [email protected] ftp://
+ ftp.ietf.org/ietf-mail-archive/secsh/2002-02.mail, Feb
+ 2002.
+
+ [BELLARE,KOHNO,NAMPREMPRE]
+ Bellaire, M., Kohno, T. and C. Namprempre, "Authenticated
+ Encryption in SSH: Fixing the SSH Binary Packet Protocol",
+ , Sept 2002.
+
+
+Authors' Addresses
+
+ Tatu Ylonen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+ Darren J. Moffat (editor)
+ Sun Microsystems, Inc
+ 17 Network Circle
+ Menlo Park CA 94025
+ USA
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 27]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+ The IETF has been notified of intellectual property rights claimed in
+ regard to some or all of the specification contained in this
+ document. For more information consult the online list of claimed
+ rights.
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 28]
+
+Internet-Draft SSH Protocol Architecture Oct 2003
+
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 31, 2004 [Page 29] \ No newline at end of file
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps
new file mode 100644
index 0000000000..7a386724c2
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.2.ps
@@ -0,0 +1,2557 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 75 0 595 747
+%%Title: Enscript Output
+%%For: Magnus Thoang
+%%Creator: GNU enscript 1.6.1
+%%CreationDate: Fri Oct 31 13:33:02 2003
+%%Orientation: Portrait
+%%Pages: 11 0
+%%DocumentMedia: A4 595 842 0 () ()
+%%DocumentNeededResources: (atend)
+%%EndComments
+%%BeginProlog
+%%BeginProcSet: PStoPS 1 15
+userdict begin
+[/showpage/erasepage/copypage]{dup where{pop dup load
+ type/operatortype eq{1 array cvx dup 0 3 index cvx put
+ bind def}{pop}ifelse}{pop}ifelse}forall
+[/letter/legal/executivepage/a4/a4small/b5/com10envelope
+ /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
+ /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
+ {pop{}def}ifelse}{pop}ifelse}forall
+/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
+ {pop def}ifelse}{def}ifelse
+/PStoPSmatrix matrix currentmatrix def
+/PStoPSxform matrix def/PStoPSclip{clippath}def
+/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
+/initmatrix{matrix defaultmatrix setmatrix}bind def
+/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
+ [{currentpoint}stopped{$error/newerror false put{newpath}}
+ {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
+ {[/newpath cvx{/moveto cvx}{/lineto cvx}
+ {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
+ stopped{$error/errorname get/invalidaccess eq{cleartomark
+ $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
+ /initclip dup load dup type dup/operatortype eq{pop exch pop}
+ {dup/arraytype eq exch/packedarraytype eq or
+ {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
+ {pop cvx}ifelse}ifelse
+ {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
+/initgraphics{initmatrix newpath initclip 1 setlinewidth
+ 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
+ 10 setmiterlimit}bind def
+end
+%%EndProcSet
+%%BeginResource: procset Enscript-Prolog 1.6 1
+%
+% Procedures.
+%
+
+/_S { % save current state
+ /_s save def
+} def
+/_R { % restore from saved state
+ _s restore
+} def
+
+/S { % showpage protecting gstate
+ gsave
+ showpage
+ grestore
+} bind def
+
+/MF { % fontname newfontname -> - make a new encoded font
+ /newfontname exch def
+ /fontname exch def
+
+ /fontdict fontname findfont def
+ /newfont fontdict maxlength dict def
+
+ fontdict {
+ exch
+ dup /FID eq {
+ % skip FID pair
+ pop pop
+ } {
+ % copy to the new font dictionary
+ exch newfont 3 1 roll put
+ } ifelse
+ } forall
+
+ newfont /FontName newfontname put
+
+ % insert only valid encoding vectors
+ encoding_vector length 256 eq {
+ newfont /Encoding encoding_vector put
+ } if
+
+ newfontname newfont definefont pop
+} def
+
+/SF { % fontname width height -> - set a new font
+ /height exch def
+ /width exch def
+
+ findfont
+ [width 0 0 height 0 0] makefont setfont
+} def
+
+/SUF { % fontname width height -> - set a new user font
+ /height exch def
+ /width exch def
+
+ /F-gs-user-font MF
+ /F-gs-user-font width height SF
+} def
+
+/M {moveto} bind def
+/s {show} bind def
+
+/Box { % x y w h -> - define box path
+ /d_h exch def /d_w exch def /d_y exch def /d_x exch def
+ d_x d_y moveto
+ d_w 0 rlineto
+ 0 d_h rlineto
+ d_w neg 0 rlineto
+ closepath
+} def
+
+/bgs { % x y height blskip gray str -> - show string with bg color
+ /str exch def
+ /gray exch def
+ /blskip exch def
+ /height exch def
+ /y exch def
+ /x exch def
+
+ gsave
+ x y blskip sub str stringwidth pop height Box
+ gray setgray
+ fill
+ grestore
+ x y M str s
+} def
+
+% Highlight bars.
+/highlight_bars { % nlines lineheight output_y_margin gray -> -
+ gsave
+ setgray
+ /ymarg exch def
+ /lineheight exch def
+ /nlines exch def
+
+ % This 2 is just a magic number to sync highlight lines to text.
+ 0 d_header_y ymarg sub 2 sub translate
+
+ /cw d_output_w cols div def
+ /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
+
+ % for each column
+ 0 1 cols 1 sub {
+ cw mul /xp exch def
+
+ % for each rows
+ 0 1 nrows 1 sub {
+ /rn exch def
+ rn lineheight mul neg /yp exch def
+ rn nlines idiv 2 mod 0 eq {
+ % Draw highlight bar. 4 is just a magic indentation.
+ xp 4 add yp cw 8 sub lineheight neg Box fill
+ } if
+ } for
+ } for
+
+ grestore
+} def
+
+% Line highlight bar.
+/line_highlight { % x y width height gray -> -
+ gsave
+ /gray exch def
+ Box gray setgray fill
+ grestore
+} def
+
+% Column separator lines.
+/column_lines {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h translate
+ /cw d_output_w cols div def
+ 1 1 cols 1 sub {
+ cw mul 0 moveto
+ 0 d_output_h rlineto stroke
+ } for
+ grestore
+} def
+
+% Column borders.
+/column_borders {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h moveto
+ 0 d_output_h rlineto
+ d_output_w 0 rlineto
+ 0 d_output_h neg rlineto
+ closepath stroke
+ grestore
+} def
+
+% Do the actual underlay drawing
+/draw_underlay {
+ ul_style 0 eq {
+ ul_str true charpath stroke
+ } {
+ ul_str show
+ } ifelse
+} def
+
+% Underlay
+/underlay { % - -> -
+ gsave
+ 0 d_page_h translate
+ d_page_h neg d_page_w atan rotate
+
+ ul_gray setgray
+ ul_font setfont
+ /dw d_page_h dup mul d_page_w dup mul add sqrt def
+ ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
+ draw_underlay
+ grestore
+} def
+
+/user_underlay { % - -> -
+ gsave
+ ul_x ul_y translate
+ ul_angle rotate
+ ul_gray setgray
+ ul_font setfont
+ 0 0 ul_h_ptsize 2 div sub moveto
+ draw_underlay
+ grestore
+} def
+
+% Page prefeed
+/page_prefeed { % bool -> -
+ statusdict /prefeed known {
+ statusdict exch /prefeed exch put
+ } {
+ pop
+ } ifelse
+} def
+
+% Wrapped line markers
+/wrapped_line_mark { % x y charwith charheight type -> -
+ /type exch def
+ /h exch def
+ /w exch def
+ /y exch def
+ /x exch def
+
+ type 2 eq {
+ % Black boxes (like TeX does)
+ gsave
+ 0 setlinewidth
+ x w 4 div add y M
+ 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
+ closepath fill
+ grestore
+ } {
+ type 3 eq {
+ % Small arrows
+ gsave
+ .2 setlinewidth
+ x w 2 div add y h 2 div add M
+ w 4 div 0 rlineto
+ x w 4 div add y lineto stroke
+
+ x w 4 div add w 8 div add y h 4 div add M
+ x w 4 div add y lineto
+ w 4 div h 8 div rlineto stroke
+ grestore
+ } {
+ % do nothing
+ } ifelse
+ } ifelse
+} def
+
+% EPSF import.
+
+/BeginEPSF {
+ /b4_Inc_state save def % Save state for cleanup
+ /dict_count countdictstack def % Count objects on dict stack
+ /op_count count 1 sub def % Count objects on operand stack
+ userdict begin
+ /showpage { } def
+ 0 setgray 0 setlinecap
+ 1 setlinewidth 0 setlinejoin
+ 10 setmiterlimit [ ] 0 setdash newpath
+ /languagelevel where {
+ pop languagelevel
+ 1 ne {
+ false setstrokeadjust false setoverprint
+ } if
+ } if
+} bind def
+
+/EndEPSF {
+ count op_count sub { pos } repeat % Clean up stacks
+ countdictstack dict_count sub { end } repeat
+ b4_Inc_state restore
+} bind def
+
+% Check PostScript language level.
+/languagelevel where {
+ pop /gs_languagelevel languagelevel def
+} {
+ /gs_languagelevel 1 def
+} ifelse
+%%EndResource
+%%BeginResource: procset Enscript-Encoding-88591 1.6 1
+/encoding_vector [
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclam /quotedbl /numbersign
+/dollar /percent /ampersand /quoteright
+/parenleft /parenright /asterisk /plus
+/comma /hyphen /period /slash
+/zero /one /two /three
+/four /five /six /seven
+/eight /nine /colon /semicolon
+/less /equal /greater /question
+/at /A /B /C
+/D /E /F /G
+/H /I /J /K
+/L /M /N /O
+/P /Q /R /S
+/T /U /V /W
+/X /Y /Z /bracketleft
+/backslash /bracketright /asciicircum /underscore
+/quoteleft /a /b /c
+/d /e /f /g
+/h /i /j /k
+/l /m /n /o
+/p /q /r /s
+/t /u /v /w
+/x /y /z /braceleft
+/bar /braceright /tilde /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclamdown /cent /sterling
+/currency /yen /brokenbar /section
+/dieresis /copyright /ordfeminine /guillemotleft
+/logicalnot /hyphen /registered /macron
+/degree /plusminus /twosuperior /threesuperior
+/acute /mu /paragraph /bullet
+/cedilla /onesuperior /ordmasculine /guillemotright
+/onequarter /onehalf /threequarters /questiondown
+/Agrave /Aacute /Acircumflex /Atilde
+/Adieresis /Aring /AE /Ccedilla
+/Egrave /Eacute /Ecircumflex /Edieresis
+/Igrave /Iacute /Icircumflex /Idieresis
+/Eth /Ntilde /Ograve /Oacute
+/Ocircumflex /Otilde /Odieresis /multiply
+/Oslash /Ugrave /Uacute /Ucircumflex
+/Udieresis /Yacute /Thorn /germandbls
+/agrave /aacute /acircumflex /atilde
+/adieresis /aring /ae /ccedilla
+/egrave /eacute /ecircumflex /edieresis
+/igrave /iacute /icircumflex /idieresis
+/eth /ntilde /ograve /oacute
+/ocircumflex /otilde /odieresis /divide
+/oslash /ugrave /uacute /ucircumflex
+/udieresis /yacute /thorn /ydieresis
+] def
+%%EndResource
+%%EndProlog
+%%BeginSetup
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier
+/HFpt_w 10 def
+/HFpt_h 10 def
+/Courier-Bold /HF-gs-font MF
+/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
+/Courier /F-gs-font MF
+/F-gs-font 10 10 SF
+/#copies 1 def
+/d_page_w 520 def
+/d_page_h 747 def
+/d_header_x 0 def
+/d_header_y 747 def
+/d_header_w 520 def
+/d_header_h 0 def
+/d_footer_x 0 def
+/d_footer_y 0 def
+/d_footer_w 520 def
+/d_footer_h 0 def
+/d_output_w 520 def
+/d_output_h 747 def
+/cols 1 def
+userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
+ matrix invertmatrix matrix concatmatrix
+ matrix invertmatrix put
+%%EndSetup
+%%Page: (0,1) 1
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 1 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 701 M
+(Network Working Group T. Ylonen) s
+5 690 M
+(Internet-Draft SSH Communications Security Corp) s
+5 679 M
+(Expires: March 31, 2004 D. Moffat, Editor, Ed.) s
+5 668 M
+( Sun Microsystems, Inc) s
+5 657 M
+( Oct 2003) s
+5 624 M
+( SSH Connection Protocol) s
+5 613 M
+( draft-ietf-secsh-connect-18.txt) s
+5 591 M
+(Status of this Memo) s
+5 569 M
+( This document is an Internet-Draft and is in full conformance with) s
+5 558 M
+( all provisions of Section 10 of RFC2026.) s
+5 536 M
+( Internet-Drafts are working documents of the Internet Engineering) s
+5 525 M
+( Task Force \(IETF\), its areas, and its working groups. Note that other) s
+5 514 M
+( groups may also distribute working documents as Internet-Drafts.) s
+5 492 M
+( Internet-Drafts are draft documents valid for a maximum of six months) s
+5 481 M
+( and may be updated, replaced, or obsoleted by other documents at any) s
+5 470 M
+( time. It is inappropriate to use Internet-Drafts as reference) s
+5 459 M
+( material or to cite them other than as "work in progress.") s
+5 437 M
+( The list of current Internet-Drafts can be accessed at http://) s
+5 426 M
+( www.ietf.org/ietf/1id-abstracts.txt.) s
+5 404 M
+( The list of Internet-Draft Shadow Directories can be accessed at) s
+5 393 M
+( http://www.ietf.org/shadow.html.) s
+5 371 M
+( This Internet-Draft will expire on March 31, 2004.) s
+5 349 M
+(Copyright Notice) s
+5 327 M
+( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
+5 305 M
+(Abstract) s
+5 283 M
+( SSH is a protocol for secure remote login and other secure network) s
+5 272 M
+( services over an insecure network.) s
+5 250 M
+( This document describes the SSH Connection Protocol. It provides) s
+5 239 M
+( interactive login sessions, remote execution of commands, forwarded) s
+5 228 M
+( TCP/IP connections, and forwarded X11 connections. All of these) s
+5 217 M
+( channels are multiplexed into a single encrypted tunnel.) s
+5 195 M
+( The SSH Connection Protocol has been designed to run on top of the) s
+5 184 M
+( SSH transport layer and user authentication protocols.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 2 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+(Table of Contents) s
+5 668 M
+( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 657 M
+( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 646 M
+( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s
+5 635 M
+( 4. Global Requests . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 624 M
+( 5. Channel Mechanism . . . . . . . . . . . . . . . . . . . . . 4) s
+5 613 M
+( 5.1 Opening a Channel . . . . . . . . . . . . . . . . . . . . . 4) s
+5 602 M
+( 5.2 Data Transfer . . . . . . . . . . . . . . . . . . . . . . . 5) s
+5 591 M
+( 5.3 Closing a Channel . . . . . . . . . . . . . . . . . . . . . 6) s
+5 580 M
+( 5.4 Channel-Specific Requests . . . . . . . . . . . . . . . . . 7) s
+5 569 M
+( 6. Interactive Sessions . . . . . . . . . . . . . . . . . . . . 8) s
+5 558 M
+( 6.1 Opening a Session . . . . . . . . . . . . . . . . . . . . . 8) s
+5 547 M
+( 6.2 Requesting a Pseudo-Terminal . . . . . . . . . . . . . . . . 8) s
+5 536 M
+( 6.3 X11 Forwarding . . . . . . . . . . . . . . . . . . . . . . . 9) s
+5 525 M
+( 6.3.1 Requesting X11 Forwarding . . . . . . . . . . . . . . . . . 9) s
+5 514 M
+( 6.3.2 X11 Channels . . . . . . . . . . . . . . . . . . . . . . . . 10) s
+5 503 M
+( 6.4 Environment Variable Passing . . . . . . . . . . . . . . . . 10) s
+5 492 M
+( 6.5 Starting a Shell or a Command . . . . . . . . . . . . . . . 10) s
+5 481 M
+( 6.6 Session Data Transfer . . . . . . . . . . . . . . . . . . . 11) s
+5 470 M
+( 6.7 Window Dimension Change Message . . . . . . . . . . . . . . 12) s
+5 459 M
+( 6.8 Local Flow Control . . . . . . . . . . . . . . . . . . . . . 12) s
+5 448 M
+( 6.9 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 12) s
+5 437 M
+( 6.10 Returning Exit Status . . . . . . . . . . . . . . . . . . . 13) s
+5 426 M
+( 7. TCP/IP Port Forwarding . . . . . . . . . . . . . . . . . . . 14) s
+5 415 M
+( 7.1 Requesting Port Forwarding . . . . . . . . . . . . . . . . . 14) s
+5 404 M
+( 7.2 TCP/IP Forwarding Channels . . . . . . . . . . . . . . . . . 15) s
+5 393 M
+( 8. Encoding of Terminal Modes . . . . . . . . . . . . . . . . . 16) s
+5 382 M
+( 9. Summary of Message Numbers . . . . . . . . . . . . . . . . . 18) s
+5 371 M
+( 10. Security Considerations . . . . . . . . . . . . . . . . . . 18) s
+5 360 M
+( 11. iana cONSiderations . . . . . . . . . . . . . . . . . . . . 19) s
+5 349 M
+( 12. Intellectual Property . . . . . . . . . . . . . . . . . . . 19) s
+5 338 M
+( Normative References . . . . . . . . . . . . . . . . . . . . 19) s
+5 327 M
+( Informative References . . . . . . . . . . . . . . . . . . . 20) s
+5 316 M
+( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 20) s
+5 305 M
+( Intellectual Property and Copyright Statements . . . . . . . 21) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (2,3) 2
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 3 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+(1. Contributors) s
+5 668 M
+( The major original contributors of this document were: Tatu Ylonen,) s
+5 657 M
+( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
+5 646 M
+( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
+5 635 M
+( Jyvaskyla\)) s
+5 613 M
+( The document editor is: [email protected]. Comments on this) s
+5 602 M
+( internet draft should be sent to the IETF SECSH working group,) s
+5 591 M
+( details at: http://ietf.org/html.charters/secsh-charter.html) s
+5 569 M
+(2. Introduction) s
+5 547 M
+( The SSH Connection Protocol has been designed to run on top of the) s
+5 536 M
+( SSH transport layer and user authentication protocols. It provides) s
+5 525 M
+( interactive login sessions, remote execution of commands, forwarded) s
+5 514 M
+( TCP/IP connections, and forwarded X11 connections. The service name) s
+5 503 M
+( for this protocol is "ssh-connection".) s
+5 481 M
+( This document should be read only after reading the SSH architecture) s
+5 470 M
+( document [SSH-ARCH]. This document freely uses terminology and) s
+5 459 M
+( notation from the architecture document without reference or further) s
+5 448 M
+( explanation.) s
+5 426 M
+(3. Conventions Used in This Document) s
+5 404 M
+( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s
+5 393 M
+( and "MAY" that appear in this document are to be interpreted as) s
+5 382 M
+( described in [RFC2119].) s
+5 360 M
+( The used data types and terminology are specified in the architecture) s
+5 349 M
+( document [SSH-ARCH].) s
+5 327 M
+( The architecture document also discusses the algorithm naming) s
+5 316 M
+( conventions that MUST be used with the SSH protocols.) s
+5 294 M
+(4. Global Requests) s
+5 272 M
+( There are several kinds of requests that affect the state of the) s
+5 261 M
+( remote end "globally", independent of any channels. An example is a) s
+5 250 M
+( request to start TCP/IP forwarding for a specific port. All such) s
+5 239 M
+( requests use the following format.) s
+5 217 M
+( byte SSH_MSG_GLOBAL_REQUEST) s
+5 206 M
+( string request name \(restricted to US-ASCII\)) s
+5 195 M
+( boolean want reply) s
+5 184 M
+( ... request-specific data follows) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 4 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( Request names follow the DNS extensibility naming convention outlined) s
+5 679 M
+( in [SSH-ARCH].) s
+5 657 M
+( The recipient will respond to this message with) s
+5 646 M
+( SSH_MSG_REQUEST_SUCCESS or SSH_MSG_REQUEST_FAILURE if `want reply' is) s
+5 635 M
+( TRUE.) s
+5 613 M
+( byte SSH_MSG_REQUEST_SUCCESS) s
+5 602 M
+( ..... response specific data) s
+5 580 M
+( Usually the response specific data is non-existent.) s
+5 558 M
+( If the recipient does not recognize or support the request, it simply) s
+5 547 M
+( responds with SSH_MSG_REQUEST_FAILURE.) s
+5 525 M
+( byte SSH_MSG_REQUEST_FAILURE) s
+5 492 M
+(5. Channel Mechanism) s
+5 470 M
+( All terminal sessions, forwarded connections, etc. are channels.) s
+5 459 M
+( Either side may open a channel. Multiple channels are multiplexed) s
+5 448 M
+( into a single connection.) s
+5 426 M
+( Channels are identified by numbers at each end. The number referring) s
+5 415 M
+( to a channel may be different on each side. Requests to open a) s
+5 404 M
+( channel contain the sender's channel number. Any other) s
+5 393 M
+( channel-related messages contain the recipient's channel number for) s
+5 382 M
+( the channel.) s
+5 360 M
+( Channels are flow-controlled. No data may be sent to a channel until) s
+5 349 M
+( a message is received to indicate that window space is available.) s
+5 327 M
+(5.1 Opening a Channel) s
+5 305 M
+( When either side wishes to open a new channel, it allocates a local) s
+5 294 M
+( number for the channel. It then sends the following message to the) s
+5 283 M
+( other side, and includes the local channel number and initial window) s
+5 272 M
+( size in the message.) s
+5 250 M
+( byte SSH_MSG_CHANNEL_OPEN) s
+5 239 M
+( string channel type \(restricted to US-ASCII\)) s
+5 228 M
+( uint32 sender channel) s
+5 217 M
+( uint32 initial window size) s
+5 206 M
+( uint32 maximum packet size) s
+5 195 M
+( ... channel type specific data follows) s
+5 173 M
+( The channel type is a name as described in the SSH architecture) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (4,5) 3
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 5 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( document, with similar extension mechanisms. `sender channel' is a) s
+5 679 M
+( local identifier for the channel used by the sender of this message.) s
+5 668 M
+( `initial window size' specifies how many bytes of channel data can be) s
+5 657 M
+( sent to the sender of this message without adjusting the window.) s
+5 646 M
+( `Maximum packet size' specifies the maximum size of an individual) s
+5 635 M
+( data packet that can be sent to the sender \(for example, one might) s
+5 624 M
+( want to use smaller packets for interactive connections to get better) s
+5 613 M
+( interactive response on slow links\).) s
+5 591 M
+( The remote side then decides whether it can open the channel, and) s
+5 580 M
+( responds with either) s
+5 558 M
+( byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION) s
+5 547 M
+( uint32 recipient channel) s
+5 536 M
+( uint32 sender channel) s
+5 525 M
+( uint32 initial window size) s
+5 514 M
+( uint32 maximum packet size) s
+5 503 M
+( ... channel type specific data follows) s
+5 481 M
+( where `recipient channel' is the channel number given in the original) s
+5 470 M
+( open request, and `sender channel' is the channel number allocated by) s
+5 459 M
+( the other side, or) s
+5 437 M
+( byte SSH_MSG_CHANNEL_OPEN_FAILURE) s
+5 426 M
+( uint32 recipient channel) s
+5 415 M
+( uint32 reason code) s
+5 404 M
+( string additional textual information \(ISO-10646 UTF-8 [RFC2279]\)) s
+5 393 M
+( string language tag \(as defined in [RFC3066]\)) s
+5 371 M
+( If the recipient of the SSH_MSG_CHANNEL_OPEN message does not support) s
+5 360 M
+( the specified channel type, it simply responds with) s
+5 349 M
+( SSH_MSG_CHANNEL_OPEN_FAILURE. The client MAY show the additional) s
+5 338 M
+( information to the user. If this is done, the client software should) s
+5 327 M
+( take the precautions discussed in [SSH-ARCH].) s
+5 305 M
+( The following reason codes are defined:) s
+5 283 M
+( #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1) s
+5 272 M
+( #define SSH_OPEN_CONNECT_FAILED 2) s
+5 261 M
+( #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3) s
+5 250 M
+( #define SSH_OPEN_RESOURCE_SHORTAGE 4) s
+5 217 M
+(5.2 Data Transfer) s
+5 195 M
+( The window size specifies how many bytes the other party can send) s
+5 184 M
+( before it must wait for the window to be adjusted. Both parties use) s
+5 173 M
+( the following message to adjust the window.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 6 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( byte SSH_MSG_CHANNEL_WINDOW_ADJUST) s
+5 679 M
+( uint32 recipient channel) s
+5 668 M
+( uint32 bytes to add) s
+5 646 M
+( After receiving this message, the recipient MAY send the given number) s
+5 635 M
+( of bytes more than it was previously allowed to send; the window size) s
+5 624 M
+( is incremented.) s
+5 602 M
+( Data transfer is done with messages of the following type.) s
+5 580 M
+( byte SSH_MSG_CHANNEL_DATA) s
+5 569 M
+( uint32 recipient channel) s
+5 558 M
+( string data) s
+5 536 M
+( The maximum amount of data allowed is the current window size. The) s
+5 525 M
+( window size is decremented by the amount of data sent. Both parties) s
+5 514 M
+( MAY ignore all extra data sent after the allowed window is empty.) s
+5 492 M
+( Additionally, some channels can transfer several types of data. An) s
+5 481 M
+( example of this is stderr data from interactive sessions. Such data) s
+5 470 M
+( can be passed with SSH_MSG_CHANNEL_EXTENDED_DATA messages, where a) s
+5 459 M
+( separate integer specifies the type of the data. The available types) s
+5 448 M
+( and their interpretation depend on the type of the channel.) s
+5 426 M
+( byte SSH_MSG_CHANNEL_EXTENDED_DATA) s
+5 415 M
+( uint32 recipient_channel) s
+5 404 M
+( uint32 data_type_code) s
+5 393 M
+( string data) s
+5 371 M
+( Data sent with these messages consumes the same window as ordinary) s
+5 360 M
+( data.) s
+5 338 M
+( Currently, only the following type is defined.) s
+5 316 M
+( #define SSH_EXTENDED_DATA_STDERR 1) s
+5 283 M
+(5.3 Closing a Channel) s
+5 261 M
+( When a party will no longer send more data to a channel, it SHOULD) s
+5 250 M
+( send SSH_MSG_CHANNEL_EOF.) s
+5 228 M
+( byte SSH_MSG_CHANNEL_EOF) s
+5 217 M
+( uint32 recipient_channel) s
+5 195 M
+( No explicit response is sent to this message; however, the) s
+5 184 M
+( application may send EOF to whatever is at the other end of the) s
+5 173 M
+( channel. Note that the channel remains open after this message, and) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (6,7) 4
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 7 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( more data may still be sent in the other direction. This message) s
+5 679 M
+( does not consume window space and can be sent even if no window space) s
+5 668 M
+( is available.) s
+5 646 M
+( When either party wishes to terminate the channel, it sends) s
+5 635 M
+( SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST) s
+5 624 M
+( send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this) s
+5 613 M
+( message for the channel. The channel is considered closed for a) s
+5 602 M
+( party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and) s
+5 591 M
+( the party may then reuse the channel number. A party MAY send) s
+5 580 M
+( SSH_MSG_CHANNEL_CLOSE without having sent or received) s
+5 569 M
+( SSH_MSG_CHANNEL_EOF.) s
+5 547 M
+( byte SSH_MSG_CHANNEL_CLOSE) s
+5 536 M
+( uint32 recipient_channel) s
+5 514 M
+( This message does not consume window space and can be sent even if no) s
+5 503 M
+( window space is available.) s
+5 481 M
+( It is recommended that any data sent before this message is delivered) s
+5 470 M
+( to the actual destination, if possible.) s
+5 448 M
+(5.4 Channel-Specific Requests) s
+5 426 M
+( Many channel types have extensions that are specific to that) s
+5 415 M
+( particular channel type. An example is requesting a pty \(pseudo) s
+5 404 M
+( terminal\) for an interactive session.) s
+5 382 M
+( All channel-specific requests use the following format.) s
+5 360 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 349 M
+( uint32 recipient channel) s
+5 338 M
+( string request type \(restricted to US-ASCII\)) s
+5 327 M
+( boolean want reply) s
+5 316 M
+( ... type-specific data) s
+5 294 M
+( If want reply is FALSE, no response will be sent to the request.) s
+5 283 M
+( Otherwise, the recipient responds with either SSH_MSG_CHANNEL_SUCCESS) s
+5 272 M
+( or SSH_MSG_CHANNEL_FAILURE, or request-specific continuation) s
+5 261 M
+( messages. If the request is not recognized or is not supported for) s
+5 250 M
+( the channel, SSH_MSG_CHANNEL_FAILURE is returned.) s
+5 228 M
+( This message does not consume window space and can be sent even if no) s
+5 217 M
+( window space is available. Request types are local to each channel) s
+5 206 M
+( type.) s
+5 184 M
+( The client is allowed to send further messages without waiting for) s
+5 173 M
+( the response to the request.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 8 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( request type names follow the DNS extensibility naming convention) s
+5 679 M
+( outlined in [SSH-ARCH]) s
+5 657 M
+( byte SSH_MSG_CHANNEL_SUCCESS) s
+5 646 M
+( uint32 recipient_channel) s
+5 613 M
+( byte SSH_MSG_CHANNEL_FAILURE) s
+5 602 M
+( uint32 recipient_channel) s
+5 580 M
+( These messages do not consume window space and can be sent even if no) s
+5 569 M
+( window space is available.) s
+5 547 M
+(6. Interactive Sessions) s
+5 525 M
+( A session is a remote execution of a program. The program may be a) s
+5 514 M
+( shell, an application, a system command, or some built-in subsystem.) s
+5 503 M
+( It may or may not have a tty, and may or may not involve X11) s
+5 492 M
+( forwarding. Multiple sessions can be active simultaneously.) s
+5 470 M
+(6.1 Opening a Session) s
+5 448 M
+( A session is started by sending the following message.) s
+5 426 M
+( byte SSH_MSG_CHANNEL_OPEN) s
+5 415 M
+( string "session") s
+5 404 M
+( uint32 sender channel) s
+5 393 M
+( uint32 initial window size) s
+5 382 M
+( uint32 maximum packet size) s
+5 360 M
+( Client implementations SHOULD reject any session channel open) s
+5 349 M
+( requests to make it more difficult for a corrupt server to attack the) s
+5 338 M
+( client.) s
+5 316 M
+(6.2 Requesting a Pseudo-Terminal) s
+5 294 M
+( A pseudo-terminal can be allocated for the session by sending the) s
+5 283 M
+( following message.) s
+5 261 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 250 M
+( uint32 recipient_channel) s
+5 239 M
+( string "pty-req") s
+5 228 M
+( boolean want_reply) s
+5 217 M
+( string TERM environment variable value \(e.g., vt100\)) s
+5 206 M
+( uint32 terminal width, characters \(e.g., 80\)) s
+5 195 M
+( uint32 terminal height, rows \(e.g., 24\)) s
+5 184 M
+( uint32 terminal width, pixels \(e.g., 640\)) s
+5 173 M
+( uint32 terminal height, pixels \(e.g., 480\)) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (8,9) 5
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 9 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( string encoded terminal modes) s
+5 668 M
+( The encoding of terminal modes is described in Section Encoding of) s
+5 657 M
+( Terminal Modes \(Section 8\). Zero dimension parameters MUST be) s
+5 646 M
+( ignored. The character/row dimensions override the pixel dimensions) s
+5 635 M
+( \(when nonzero\). Pixel dimensions refer to the drawable area of the) s
+5 624 M
+( window.) s
+5 602 M
+( The dimension parameters are only informational.) s
+5 580 M
+( The client SHOULD ignore pty requests.) s
+5 558 M
+(6.3 X11 Forwarding) s
+5 536 M
+(6.3.1 Requesting X11 Forwarding) s
+5 514 M
+( X11 forwarding may be requested for a session by sending) s
+5 492 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 481 M
+( uint32 recipient channel) s
+5 470 M
+( string "x11-req") s
+5 459 M
+( boolean want reply) s
+5 448 M
+( boolean single connection) s
+5 437 M
+( string x11 authentication protocol) s
+5 426 M
+( string x11 authentication cookie) s
+5 415 M
+( uint32 x11 screen number) s
+5 393 M
+( It is recommended that the authentication cookie that is sent be a) s
+5 382 M
+( fake, random cookie, and that the cookie is checked and replaced by) s
+5 371 M
+( the real cookie when a connection request is received.) s
+5 349 M
+( X11 connection forwarding should stop when the session channel is) s
+5 338 M
+( closed; however, already opened forwardings should not be) s
+5 327 M
+( automatically closed when the session channel is closed.) s
+5 305 M
+( If `single connection' is TRUE, only a single connection should be) s
+5 294 M
+( forwarded. No more connections will be forwarded after the first, or) s
+5 283 M
+( after the session channel has been closed.) s
+5 261 M
+( The "x11 authentication protocol" is the name of the X11) s
+5 250 M
+( authentication method used, e.g. "MIT-MAGIC-COOKIE-1".) s
+5 228 M
+( The x11 authentication cookie MUST be hexadecimal encoded.) s
+5 206 M
+( X Protocol is documented in [SCHEIFLER].) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 10 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+(6.3.2 X11 Channels) s
+5 668 M
+( X11 channels are opened with a channel open request. The resulting) s
+5 657 M
+( channels are independent of the session, and closing the session) s
+5 646 M
+( channel does not close the forwarded X11 channels.) s
+5 624 M
+( byte SSH_MSG_CHANNEL_OPEN) s
+5 613 M
+( string "x11") s
+5 602 M
+( uint32 sender channel) s
+5 591 M
+( uint32 initial window size) s
+5 580 M
+( uint32 maximum packet size) s
+5 569 M
+( string originator address \(e.g. "192.168.7.38"\)) s
+5 558 M
+( uint32 originator port) s
+5 536 M
+( The recipient should respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION) s
+5 525 M
+( or SSH_MSG_CHANNEL_OPEN_FAILURE.) s
+5 503 M
+( Implementations MUST reject any X11 channel open requests if they) s
+5 492 M
+( have not requested X11 forwarding.) s
+5 470 M
+(6.4 Environment Variable Passing) s
+5 448 M
+( Environment variables may be passed to the shell/command to be) s
+5 437 M
+( started later. Uncontrolled setting of environment variables in a) s
+5 426 M
+( privileged process can be a security hazard. It is recommended that) s
+5 415 M
+( implementations either maintain a list of allowable variable names or) s
+5 404 M
+( only set environment variables after the server process has dropped) s
+5 393 M
+( sufficient privileges.) s
+5 371 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 360 M
+( uint32 recipient channel) s
+5 349 M
+( string "env") s
+5 338 M
+( boolean want reply) s
+5 327 M
+( string variable name) s
+5 316 M
+( string variable value) s
+5 283 M
+(6.5 Starting a Shell or a Command) s
+5 261 M
+( Once the session has been set up, a program is started at the remote) s
+5 250 M
+( end. The program can be a shell, an application program or a) s
+5 239 M
+( subsystem with a host-independent name. Only one of these requests) s
+5 228 M
+( can succeed per channel.) s
+5 206 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 195 M
+( uint32 recipient channel) s
+5 184 M
+( string "shell") s
+5 173 M
+( boolean want reply) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (10,11) 6
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 11 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( This message will request the user's default shell \(typically defined) s
+5 679 M
+( in /etc/passwd in UNIX systems\) to be started at the other end.) s
+5 657 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 646 M
+( uint32 recipient channel) s
+5 635 M
+( string "exec") s
+5 624 M
+( boolean want reply) s
+5 613 M
+( string command) s
+5 591 M
+( This message will request the server to start the execution of the) s
+5 580 M
+( given command. The command string may contain a path. Normal) s
+5 569 M
+( precautions MUST be taken to prevent the execution of unauthorized) s
+5 558 M
+( commands.) s
+5 536 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 525 M
+( uint32 recipient channel) s
+5 514 M
+( string "subsystem") s
+5 503 M
+( boolean want reply) s
+5 492 M
+( string subsystem name) s
+5 470 M
+( This last form executes a predefined subsystem. It is expected that) s
+5 459 M
+( these will include a general file transfer mechanism, and possibly) s
+5 448 M
+( other features. Implementations may also allow configuring more such) s
+5 437 M
+( mechanisms. As the user's shell is usually used to execute the) s
+5 426 M
+( subsystem, it is advisable for the subsystem protocol to have a) s
+5 415 M
+( "magic cookie" at the beginning of the protocol transaction to) s
+5 404 M
+( distinguish it from arbitrary output generated by shell) s
+5 393 M
+( initialization scripts etc. This spurious output from the shell may) s
+5 382 M
+( be filtered out either at the server or at the client.) s
+5 360 M
+( The server SHOULD not halt the execution of the protocol stack when) s
+5 349 M
+( starting a shell or a program. All input and output from these SHOULD) s
+5 338 M
+( be redirected to the channel or to the encrypted tunnel.) s
+5 316 M
+( It is RECOMMENDED to request and check the reply for these messages.) s
+5 305 M
+( The client SHOULD ignore these messages.) s
+5 283 M
+( Subsystem names follow the DNS extensibility naming convention) s
+5 272 M
+( outlined in [SSH-ARCH].) s
+5 250 M
+(6.6 Session Data Transfer) s
+5 228 M
+( Data transfer for a session is done using SSH_MSG_CHANNEL_DATA and) s
+5 217 M
+( SSH_MSG_CHANNEL_EXTENDED_DATA packets and the window mechanism. The) s
+5 206 M
+( extended data type SSH_EXTENDED_DATA_STDERR has been defined for) s
+5 195 M
+( stderr data.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 12 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+(6.7 Window Dimension Change Message) s
+5 668 M
+( When the window \(terminal\) size changes on the client side, it MAY) s
+5 657 M
+( send a message to the other side to inform it of the new dimensions.) s
+5 635 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 624 M
+( uint32 recipient_channel) s
+5 613 M
+( string "window-change") s
+5 602 M
+( boolean FALSE) s
+5 591 M
+( uint32 terminal width, columns) s
+5 580 M
+( uint32 terminal height, rows) s
+5 569 M
+( uint32 terminal width, pixels) s
+5 558 M
+( uint32 terminal height, pixels) s
+5 536 M
+( No response SHOULD be sent to this message.) s
+5 514 M
+(6.8 Local Flow Control) s
+5 492 M
+( On many systems, it is possible to determine if a pseudo-terminal is) s
+5 481 M
+( using control-S/control-Q flow control. When flow control is) s
+5 470 M
+( allowed, it is often desirable to do the flow control at the client) s
+5 459 M
+( end to speed up responses to user requests. This is facilitated by) s
+5 448 M
+( the following notification. Initially, the server is responsible for) s
+5 437 M
+( flow control. \(Here, again, client means the side originating the) s
+5 426 M
+( session, and server means the other side.\)) s
+5 404 M
+( The message below is used by the server to inform the client when it) s
+5 393 M
+( can or cannot perform flow control \(control-S/control-Q processing\).) s
+5 382 M
+( If `client can do' is TRUE, the client is allowed to do flow control) s
+5 371 M
+( using control-S and control-Q. The client MAY ignore this message.) s
+5 349 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 338 M
+( uint32 recipient channel) s
+5 327 M
+( string "xon-xoff") s
+5 316 M
+( boolean FALSE) s
+5 305 M
+( boolean client can do) s
+5 283 M
+( No response is sent to this message.) s
+5 261 M
+(6.9 Signals) s
+5 239 M
+( A signal can be delivered to the remote process/service using the) s
+5 228 M
+( following message. Some systems may not implement signals, in which) s
+5 217 M
+( case they SHOULD ignore this message.) s
+5 195 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 184 M
+( uint32 recipient channel) s
+5 173 M
+( string "signal") s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (12,13) 7
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 13 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( boolean FALSE) s
+5 679 M
+( string signal name without the "SIG" prefix.) s
+5 657 M
+( Signal names will be encoded as discussed in the "exit-signal") s
+5 646 M
+( SSH_MSG_CHANNEL_REQUEST.) s
+5 624 M
+(6.10 Returning Exit Status) s
+5 602 M
+( When the command running at the other end terminates, the following) s
+5 591 M
+( message can be sent to return the exit status of the command.) s
+5 580 M
+( Returning the status is RECOMMENDED. No acknowledgment is sent for) s
+5 569 M
+( this message. The channel needs to be closed with) s
+5 558 M
+( SSH_MSG_CHANNEL_CLOSE after this message.) s
+5 536 M
+( The client MAY ignore these messages.) s
+5 514 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 503 M
+( uint32 recipient_channel) s
+5 492 M
+( string "exit-status") s
+5 481 M
+( boolean FALSE) s
+5 470 M
+( uint32 exit_status) s
+5 448 M
+( The remote command may also terminate violently due to a signal.) s
+5 437 M
+( Such a condition can be indicated by the following message. A zero) s
+5 426 M
+( exit_status usually means that the command terminated successfully.) s
+5 404 M
+( byte SSH_MSG_CHANNEL_REQUEST) s
+5 393 M
+( uint32 recipient channel) s
+5 382 M
+( string "exit-signal") s
+5 371 M
+( boolean FALSE) s
+5 360 M
+( string signal name without the "SIG" prefix.) s
+5 349 M
+( boolean core dumped) s
+5 338 M
+( string error message \(ISO-10646 UTF-8\)) s
+5 327 M
+( string language tag \(as defined in [RFC3066]\)) s
+5 305 M
+( The signal name is one of the following \(these are from [POSIX]\)) s
+5 283 M
+( ABRT) s
+5 272 M
+( ALRM) s
+5 261 M
+( FPE) s
+5 250 M
+( HUP) s
+5 239 M
+( ILL) s
+5 228 M
+( INT) s
+5 217 M
+( KILL) s
+5 206 M
+( PIPE) s
+5 195 M
+( QUIT) s
+5 184 M
+( SEGV) s
+5 173 M
+( TERM) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 14 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( USR1) s
+5 679 M
+( USR2) s
+5 657 M
+( Additional signal names MAY be sent in the format "sig-name@xyz",) s
+5 646 M
+( where `sig-name' and `xyz' may be anything a particular implementor) s
+5 635 M
+( wants \(except the `@' sign\). However, it is suggested that if a) s
+5 624 M
+( `configure' script is used, the non-standard signal names it finds be) s
+5 613 M
+( encoded as "[email protected]", where `SIG' is the signal name) s
+5 602 M
+( without the "SIG" prefix, and `xyz' be the host type, as determined) s
+5 591 M
+( by `config.guess'.) s
+5 569 M
+( The `error message' contains an additional explanation of the error) s
+5 558 M
+( message. The message may consist of multiple lines. The client) s
+5 547 M
+( software MAY display this message to the user. If this is done, the) s
+5 536 M
+( client software should take the precautions discussed in [SSH-ARCH].) s
+5 514 M
+(7. TCP/IP Port Forwarding) s
+5 492 M
+(7.1 Requesting Port Forwarding) s
+5 470 M
+( A party need not explicitly request forwardings from its own end to) s
+5 459 M
+( the other direction. However, if it wishes that connections to a) s
+5 448 M
+( port on the other side be forwarded to the local side, it must) s
+5 437 M
+( explicitly request this.) s
+5 404 M
+( byte SSH_MSG_GLOBAL_REQUEST) s
+5 393 M
+( string "tcpip-forward") s
+5 382 M
+( boolean want reply) s
+5 371 M
+( string address to bind \(e.g. "0.0.0.0"\)) s
+5 360 M
+( uint32 port number to bind) s
+5 338 M
+( `Address to bind' and `port number to bind' specify the IP address) s
+5 327 M
+( and port to which the socket to be listened is bound. The address) s
+5 316 M
+( should be "0.0.0.0" if connections are allowed from anywhere. \(Note) s
+5 305 M
+( that the client can still filter connections based on information) s
+5 294 M
+( passed in the open request.\)) s
+5 272 M
+( Implementations should only allow forwarding privileged ports if the) s
+5 261 M
+( user has been authenticated as a privileged user.) s
+5 239 M
+( Client implementations SHOULD reject these messages; they are) s
+5 228 M
+( normally only sent by the client.) s
+5 195 M
+( If a client passes 0 as port number to bind and has want reply TRUE) s
+5 184 M
+( then the server allocates the next available unprivileged port number) s
+5 173 M
+( and replies with the following message, otherwise there is no) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (14,15) 8
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 15 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( response specific data.) s
+5 657 M
+( byte SSH_MSG_GLOBAL_REQUEST_SUCCESS) s
+5 646 M
+( uint32 port that was bound on the server) s
+5 624 M
+( A port forwarding can be cancelled with the following message. Note) s
+5 613 M
+( that channel open requests may be received until a reply to this) s
+5 602 M
+( message is received.) s
+5 580 M
+( byte SSH_MSG_GLOBAL_REQUEST) s
+5 569 M
+( string "cancel-tcpip-forward") s
+5 558 M
+( boolean want reply) s
+5 547 M
+( string address_to_bind \(e.g. "127.0.0.1"\)) s
+5 536 M
+( uint32 port number to bind) s
+5 514 M
+( Client implementations SHOULD reject these messages; they are) s
+5 503 M
+( normally only sent by the client.) s
+5 481 M
+(7.2 TCP/IP Forwarding Channels) s
+5 459 M
+( When a connection comes to a port for which remote forwarding has) s
+5 448 M
+( been requested, a channel is opened to forward the port to the other) s
+5 437 M
+( side.) s
+5 415 M
+( byte SSH_MSG_CHANNEL_OPEN) s
+5 404 M
+( string "forwarded-tcpip") s
+5 393 M
+( uint32 sender channel) s
+5 382 M
+( uint32 initial window size) s
+5 371 M
+( uint32 maximum packet size) s
+5 360 M
+( string address that was connected) s
+5 349 M
+( uint32 port that was connected) s
+5 338 M
+( string originator IP address) s
+5 327 M
+( uint32 originator port) s
+5 305 M
+( Implementations MUST reject these messages unless they have) s
+5 294 M
+( previously requested a remote TCP/IP port forwarding with the given) s
+5 283 M
+( port number.) s
+5 261 M
+( When a connection comes to a locally forwarded TCP/IP port, the) s
+5 250 M
+( following packet is sent to the other side. Note that these messages) s
+5 239 M
+( MAY be sent also for ports for which no forwarding has been) s
+5 228 M
+( explicitly requested. The receiving side must decide whether to) s
+5 217 M
+( allow the forwarding.) s
+5 195 M
+( byte SSH_MSG_CHANNEL_OPEN) s
+5 184 M
+( string "direct-tcpip") s
+5 173 M
+( uint32 sender channel) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 16 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( uint32 initial window size) s
+5 679 M
+( uint32 maximum packet size) s
+5 668 M
+( string host to connect) s
+5 657 M
+( uint32 port to connect) s
+5 646 M
+( string originator IP address) s
+5 635 M
+( uint32 originator port) s
+5 613 M
+( `Host to connect' and `port to connect' specify the TCP/IP host and) s
+5 602 M
+( port where the recipient should connect the channel. `Host to) s
+5 591 M
+( connect' may be either a domain name or a numeric IP address.) s
+5 569 M
+( `Originator IP address' is the numeric IP address of the machine) s
+5 558 M
+( where the connection request comes from, and `originator port' is the) s
+5 547 M
+( port on the originator host from where the connection came from.) s
+5 525 M
+( Forwarded TCP/IP channels are independent of any sessions, and) s
+5 514 M
+( closing a session channel does not in any way imply that forwarded) s
+5 503 M
+( connections should be closed.) s
+5 481 M
+( Client implementations SHOULD reject direct TCP/IP open requests for) s
+5 470 M
+( security reasons.) s
+5 448 M
+(8. Encoding of Terminal Modes) s
+5 426 M
+( Terminal modes \(as passed in a pty request\) are encoded into a byte) s
+5 415 M
+( stream. It is intended that the coding be portable across different) s
+5 404 M
+( environments.) s
+5 382 M
+( The tty mode description is a stream of bytes. The stream consists) s
+5 371 M
+( of opcode-argument pairs. It is terminated by opcode TTY_OP_END \(0\).) s
+5 360 M
+( Opcodes 1 to 159 have a single uint32 argument. Opcodes 160 to 255) s
+5 349 M
+( are not yet defined, and cause parsing to stop \(they should only be) s
+5 338 M
+( used after any other data\).) s
+5 316 M
+( The client SHOULD put in the stream any modes it knows about, and the) s
+5 305 M
+( server MAY ignore any modes it does not know about. This allows some) s
+5 294 M
+( degree of machine-independence, at least between systems that use a) s
+5 283 M
+( POSIX-like tty interface. The protocol can support other systems as) s
+5 272 M
+( well, but the client may need to fill reasonable values for a number) s
+5 261 M
+( of parameters so the server pty gets set to a reasonable mode \(the) s
+5 250 M
+( server leaves all unspecified mode bits in their default values, and) s
+5 239 M
+( only some combinations make sense\).) s
+5 217 M
+( The following opcodes have been defined. The naming of opcodes) s
+5 206 M
+( mostly follows the POSIX terminal mode flags.) s
+5 184 M
+( 0 TTY_OP_END Indicates end of options.) s
+5 173 M
+( 1 VINTR Interrupt character; 255 if none. Similarly for the) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (16,17) 9
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 17 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( other characters. Not all of these characters are) s
+5 679 M
+( supported on all systems.) s
+5 668 M
+( 2 VQUIT The quit character \(sends SIGQUIT signal on POSIX) s
+5 657 M
+( systems\).) s
+5 646 M
+( 3 VERASE Erase the character to left of the cursor.) s
+5 635 M
+( 4 VKILL Kill the current input line.) s
+5 624 M
+( 5 VEOF End-of-file character \(sends EOF from the terminal\).) s
+5 613 M
+( 6 VEOL End-of-line character in addition to carriage return) s
+5 602 M
+( and/or linefeed.) s
+5 591 M
+( 7 VEOL2 Additional end-of-line character.) s
+5 580 M
+( 8 VSTART Continues paused output \(normally control-Q\).) s
+5 569 M
+( 9 VSTOP Pauses output \(normally control-S\).) s
+5 558 M
+( 10 VSUSP Suspends the current program.) s
+5 547 M
+( 11 VDSUSP Another suspend character.) s
+5 536 M
+( 12 VREPRINT Reprints the current input line.) s
+5 525 M
+( 13 VWERASE Erases a word left of cursor.) s
+5 514 M
+( 14 VLNEXT Enter the next character typed literally, even if it) s
+5 503 M
+( is a special character) s
+5 492 M
+( 15 VFLUSH Character to flush output.) s
+5 481 M
+( 16 VSWTCH Switch to a different shell layer.) s
+5 470 M
+( 17 VSTATUS Prints system status line \(load, command, pid etc\).) s
+5 459 M
+( 18 VDISCARD Toggles the flushing of terminal output.) s
+5 448 M
+( 30 IGNPAR The ignore parity flag. The parameter SHOULD be 0 if) s
+5 437 M
+( this flag is FALSE set, and 1 if it is TRUE.) s
+5 426 M
+( 31 PARMRK Mark parity and framing errors.) s
+5 415 M
+( 32 INPCK Enable checking of parity errors.) s
+5 404 M
+( 33 ISTRIP Strip 8th bit off characters.) s
+5 393 M
+( 34 INLCR Map NL into CR on input.) s
+5 382 M
+( 35 IGNCR Ignore CR on input.) s
+5 371 M
+( 36 ICRNL Map CR to NL on input.) s
+5 360 M
+( 37 IUCLC Translate uppercase characters to lowercase.) s
+5 349 M
+( 38 IXON Enable output flow control.) s
+5 338 M
+( 39 IXANY Any char will restart after stop.) s
+5 327 M
+( 40 IXOFF Enable input flow control.) s
+5 316 M
+( 41 IMAXBEL Ring bell on input queue full.) s
+5 305 M
+( 50 ISIG Enable signals INTR, QUIT, [D]SUSP.) s
+5 294 M
+( 51 ICANON Canonicalize input lines.) s
+5 283 M
+( 52 XCASE Enable input and output of uppercase characters by) s
+5 272 M
+( preceding their lowercase equivalents with `\\'.) s
+5 261 M
+( 53 ECHO Enable echoing.) s
+5 250 M
+( 54 ECHOE Visually erase chars.) s
+5 239 M
+( 55 ECHOK Kill character discards current line.) s
+5 228 M
+( 56 ECHONL Echo NL even if ECHO is off.) s
+5 217 M
+( 57 NOFLSH Don't flush after interrupt.) s
+5 206 M
+( 58 TOSTOP Stop background jobs from output.) s
+5 195 M
+( 59 IEXTEN Enable extensions.) s
+5 184 M
+( 60 ECHOCTL Echo control characters as ^\(Char\).) s
+5 173 M
+( 61 ECHOKE Visual erase for line kill.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 18 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( 62 PENDIN Retype pending input.) s
+5 679 M
+( 70 OPOST Enable output processing.) s
+5 668 M
+( 71 OLCUC Convert lowercase to uppercase.) s
+5 657 M
+( 72 ONLCR Map NL to CR-NL.) s
+5 646 M
+( 73 OCRNL Translate carriage return to newline \(output\).) s
+5 635 M
+( 74 ONOCR Translate newline to carriage return-newline) s
+5 624 M
+( \(output\).) s
+5 613 M
+( 75 ONLRET Newline performs a carriage return \(output\).) s
+5 602 M
+( 90 CS7 7 bit mode.) s
+5 591 M
+( 91 CS8 8 bit mode.) s
+5 580 M
+( 92 PARENB Parity enable.) s
+5 569 M
+( 93 PARODD Odd parity, else even.) s
+5 547 M
+( 128 TTY_OP_ISPEED Specifies the input baud rate in bits per second.) s
+5 536 M
+( 129 TTY_OP_OSPEED Specifies the output baud rate in bits per second.) s
+5 503 M
+(9. Summary of Message Numbers) s
+5 481 M
+( #define SSH_MSG_GLOBAL_REQUEST 80) s
+5 470 M
+( #define SSH_MSG_REQUEST_SUCCESS 81) s
+5 459 M
+( #define SSH_MSG_REQUEST_FAILURE 82) s
+5 448 M
+( #define SSH_MSG_CHANNEL_OPEN 90) s
+5 437 M
+( #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91) s
+5 426 M
+( #define SSH_MSG_CHANNEL_OPEN_FAILURE 92) s
+5 415 M
+( #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93) s
+5 404 M
+( #define SSH_MSG_CHANNEL_DATA 94) s
+5 393 M
+( #define SSH_MSG_CHANNEL_EXTENDED_DATA 95) s
+5 382 M
+( #define SSH_MSG_CHANNEL_EOF 96) s
+5 371 M
+( #define SSH_MSG_CHANNEL_CLOSE 97) s
+5 360 M
+( #define SSH_MSG_CHANNEL_REQUEST 98) s
+5 349 M
+( #define SSH_MSG_CHANNEL_SUCCESS 99) s
+5 338 M
+( #define SSH_MSG_CHANNEL_FAILURE 100) s
+5 305 M
+(10. Security Considerations) s
+5 283 M
+( This protocol is assumed to run on top of a secure, authenticated) s
+5 272 M
+( transport. User authentication and protection against network-level) s
+5 261 M
+( attacks are assumed to be provided by the underlying protocols.) s
+5 239 M
+( It is RECOMMENDED that implementations disable all the potentially) s
+5 228 M
+( dangerous features \(e.g. agent forwarding, X11 forwarding, and TCP/IP) s
+5 217 M
+( forwarding\) if the host key has changed.) s
+5 195 M
+( Full security considerations for this protocol are provided in) s
+5 184 M
+( Section 8 of [SSH-ARCH]) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (18,19) 10
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 19 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+(11. iana cONSiderations) s
+5 668 M
+( This document is part of a set, the IANA considerations for the SSH) s
+5 657 M
+( protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],) s
+5 646 M
+( [SSH-CONNECT] are detailed in [SSH-NUMBERS].) s
+5 624 M
+(12. Intellectual Property) s
+5 602 M
+( The IETF takes no position regarding the validity or scope of any) s
+5 591 M
+( intellectual property or other rights that might be claimed to) s
+5 580 M
+( pertain to the implementation or use of the technology described in) s
+5 569 M
+( this document or the extent to which any license under such rights) s
+5 558 M
+( might or might not be available; neither does it represent that it) s
+5 547 M
+( has made any effort to identify any such rights. Information on the) s
+5 536 M
+( IETF's procedures with respect to rights in standards-track and) s
+5 525 M
+( standards-related documentation can be found in BCP-11. Copies of) s
+5 514 M
+( claims of rights made available for publication and any assurances of) s
+5 503 M
+( licenses to be made available, or the result of an attempt made to) s
+5 492 M
+( obtain a general license or permission for the use of such) s
+5 481 M
+( proprietary rights by implementers or users of this specification can) s
+5 470 M
+( be obtained from the IETF Secretariat.) s
+5 448 M
+( The IETF has been notified of intellectual property rights claimed in) s
+5 437 M
+( regard to some or all of the specification contained in this) s
+5 426 M
+( document. For more information consult the online list of claimed) s
+5 415 M
+( rights.) s
+5 393 M
+(Normative References) s
+5 371 M
+( [SSH-ARCH]) s
+5 360 M
+( Ylonen, T., "SSH Protocol Architecture", I-D) s
+5 349 M
+( draft-ietf-architecture-15.txt, Oct 2003.) s
+5 327 M
+( [SSH-TRANS]) s
+5 316 M
+( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
+5 305 M
+( draft-ietf-transport-17.txt, Oct 2003.) s
+5 283 M
+( [SSH-USERAUTH]) s
+5 272 M
+( Ylonen, T., "SSH Authentication Protocol", I-D) s
+5 261 M
+( draft-ietf-userauth-18.txt, Oct 2003.) s
+5 239 M
+( [SSH-CONNECT]) s
+5 228 M
+( Ylonen, T., "SSH Connection Protocol", I-D) s
+5 217 M
+( draft-ietf-connect-18.txt, Oct 2003.) s
+5 195 M
+( [SSH-NUMBERS]) s
+5 184 M
+( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
+5 173 M
+( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 20 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( 2003.) s
+5 668 M
+( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
+5 657 M
+( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
+5 635 M
+(Informative References) s
+5 613 M
+( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
+5 602 M
+( Languages", BCP 47, RFC 3066, January 2001.) s
+5 580 M
+( [RFC1884] Hinden, R. and S. Deering, "IP Version 6 Addressing) s
+5 569 M
+( Architecture", RFC 1884, December 1995.) s
+5 547 M
+( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
+5 536 M
+( 10646", RFC 2279, January 1998.) s
+5 514 M
+( [SCHEIFLER]) s
+5 503 M
+( Scheifler, R., "X Window System : The Complete Reference) s
+5 492 M
+( to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital) s
+5 481 M
+( Press ISBN 1555580882, Feburary 1992.) s
+5 459 M
+( [POSIX] ISO/IEC, 9945-1., "Information technology -- Portable) s
+5 448 M
+( Operating System Interface \(POSIX\)-Part 1: System) s
+5 437 M
+( Application Program Interface \(API\) C Language", ANSI/IEE) s
+5 426 M
+( Std 1003.1, July 1996.) s
+5 393 M
+(Authors' Addresses) s
+5 371 M
+( Tatu Ylonen) s
+5 360 M
+( SSH Communications Security Corp) s
+5 349 M
+( Fredrikinkatu 42) s
+5 338 M
+( HELSINKI FIN-00100) s
+5 327 M
+( Finland) s
+5 305 M
+( EMail: [email protected]) s
+5 272 M
+( Darren J. Moffat \(editor\)) s
+5 261 M
+( Sun Microsystems, Inc) s
+5 250 M
+( 17 Network Circle) s
+5 239 M
+( Menlo Park CA 94025) s
+5 228 M
+( USA) s
+5 206 M
+( EMail: [email protected]) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (20,21) 11
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 21 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+(Intellectual Property Statement) s
+5 668 M
+( The IETF takes no position regarding the validity or scope of any) s
+5 657 M
+( intellectual property or other rights that might be claimed to) s
+5 646 M
+( pertain to the implementation or use of the technology described in) s
+5 635 M
+( this document or the extent to which any license under such rights) s
+5 624 M
+( might or might not be available; neither does it represent that it) s
+5 613 M
+( has made any effort to identify any such rights. Information on the) s
+5 602 M
+( IETF's procedures with respect to rights in standards-track and) s
+5 591 M
+( standards-related documentation can be found in BCP-11. Copies of) s
+5 580 M
+( claims of rights made available for publication and any assurances of) s
+5 569 M
+( licenses to be made available, or the result of an attempt made to) s
+5 558 M
+( obtain a general license or permission for the use of such) s
+5 547 M
+( proprietary rights by implementors or users of this specification can) s
+5 536 M
+( be obtained from the IETF Secretariat.) s
+5 514 M
+( The IETF invites any interested party to bring to its attention any) s
+5 503 M
+( copyrights, patents or patent applications, or other proprietary) s
+5 492 M
+( rights which may cover technology that may be required to practice) s
+5 481 M
+( this standard. Please address the information to the IETF Executive) s
+5 470 M
+( Director.) s
+5 448 M
+( The IETF has been notified of intellectual property rights claimed in) s
+5 437 M
+( regard to some or all of the specification contained in this) s
+5 426 M
+( document. For more information consult the online list of claimed) s
+5 415 M
+( rights.) s
+5 382 M
+(Full Copyright Statement) s
+5 360 M
+( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
+5 338 M
+( This document and translations of it may be copied and furnished to) s
+5 327 M
+( others, and derivative works that comment on or otherwise explain it) s
+5 316 M
+( or assist in its implementation may be prepared, copied, published) s
+5 305 M
+( and distributed, in whole or in part, without restriction of any) s
+5 294 M
+( kind, provided that the above copyright notice and this paragraph are) s
+5 283 M
+( included on all such copies and derivative works. However, this) s
+5 272 M
+( document itself may not be modified in any way, such as by removing) s
+5 261 M
+( the copyright notice or references to the Internet Society or other) s
+5 250 M
+( Internet organizations, except as needed for the purpose of) s
+5 239 M
+( developing Internet standards in which case the procedures for) s
+5 228 M
+( copyrights defined in the Internet Standards process must be) s
+5 217 M
+( followed, or as required to translate it into languages other than) s
+5 206 M
+( English.) s
+5 184 M
+( The limited permissions granted above are perpetual and will not be) s
+5 173 M
+( revoked by the Internet Society or its successors or assignees.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 22 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Connection Protocol Oct 2003) s
+5 690 M
+( This document and the information contained herein is provided on an) s
+5 679 M
+( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
+5 668 M
+( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
+5 657 M
+( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
+5 646 M
+( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
+5 635 M
+( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
+5 602 M
+(Acknowledgment) s
+5 580 M
+( Funding for the RFC Editor function is currently provided by the) s
+5 569 M
+( Internet Society.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]) s
+_R
+S
+PStoPSsaved restore
+%%Trailer
+%%Pages: 22
+%%DocumentNeededResources: font Courier-Bold Courier
+%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt
new file mode 100644
index 0000000000..1cb8ad6409
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-connect-18.txt
@@ -0,0 +1,1232 @@
+
+
+
+Network Working Group T. Ylonen
+Internet-Draft SSH Communications Security Corp
+Expires: March 31, 2004 D. Moffat, Editor, Ed.
+ Sun Microsystems, Inc
+ Oct 2003
+
+
+ SSH Connection Protocol
+ draft-ietf-secsh-connect-18.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that other
+ groups may also distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on March 31, 2004.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ SSH is a protocol for secure remote login and other secure network
+ services over an insecure network.
+
+ This document describes the SSH Connection Protocol. It provides
+ interactive login sessions, remote execution of commands, forwarded
+ TCP/IP connections, and forwarded X11 connections. All of these
+ channels are multiplexed into a single encrypted tunnel.
+
+ The SSH Connection Protocol has been designed to run on top of the
+ SSH transport layer and user authentication protocols.
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+Table of Contents
+
+ 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Conventions Used in This Document . . . . . . . . . . . . . 3
+ 4. Global Requests . . . . . . . . . . . . . . . . . . . . . . 3
+ 5. Channel Mechanism . . . . . . . . . . . . . . . . . . . . . 4
+ 5.1 Opening a Channel . . . . . . . . . . . . . . . . . . . . . 4
+ 5.2 Data Transfer . . . . . . . . . . . . . . . . . . . . . . . 5
+ 5.3 Closing a Channel . . . . . . . . . . . . . . . . . . . . . 6
+ 5.4 Channel-Specific Requests . . . . . . . . . . . . . . . . . 7
+ 6. Interactive Sessions . . . . . . . . . . . . . . . . . . . . 8
+ 6.1 Opening a Session . . . . . . . . . . . . . . . . . . . . . 8
+ 6.2 Requesting a Pseudo-Terminal . . . . . . . . . . . . . . . . 8
+ 6.3 X11 Forwarding . . . . . . . . . . . . . . . . . . . . . . . 9
+ 6.3.1 Requesting X11 Forwarding . . . . . . . . . . . . . . . . . 9
+ 6.3.2 X11 Channels . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 6.4 Environment Variable Passing . . . . . . . . . . . . . . . . 10
+ 6.5 Starting a Shell or a Command . . . . . . . . . . . . . . . 10
+ 6.6 Session Data Transfer . . . . . . . . . . . . . . . . . . . 11
+ 6.7 Window Dimension Change Message . . . . . . . . . . . . . . 12
+ 6.8 Local Flow Control . . . . . . . . . . . . . . . . . . . . . 12
+ 6.9 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 12
+ 6.10 Returning Exit Status . . . . . . . . . . . . . . . . . . . 13
+ 7. TCP/IP Port Forwarding . . . . . . . . . . . . . . . . . . . 14
+ 7.1 Requesting Port Forwarding . . . . . . . . . . . . . . . . . 14
+ 7.2 TCP/IP Forwarding Channels . . . . . . . . . . . . . . . . . 15
+ 8. Encoding of Terminal Modes . . . . . . . . . . . . . . . . . 16
+ 9. Summary of Message Numbers . . . . . . . . . . . . . . . . . 18
+ 10. Security Considerations . . . . . . . . . . . . . . . . . . 18
+ 11. iana cONSiderations . . . . . . . . . . . . . . . . . . . . 19
+ 12. Intellectual Property . . . . . . . . . . . . . . . . . . . 19
+ Normative References . . . . . . . . . . . . . . . . . . . . 19
+ Informative References . . . . . . . . . . . . . . . . . . . 20
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 20
+ Intellectual Property and Copyright Statements . . . . . . . 21
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+1. Contributors
+
+ The major original contributors of this document were: Tatu Ylonen,
+ Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
+ Security Corp), and Markku-Juhani O. Saarinen (University of
+ Jyvaskyla)
+
+ The document editor is: [email protected]. Comments on this
+ internet draft should be sent to the IETF SECSH working group,
+ details at: http://ietf.org/html.charters/secsh-charter.html
+
+2. Introduction
+
+ The SSH Connection Protocol has been designed to run on top of the
+ SSH transport layer and user authentication protocols. It provides
+ interactive login sessions, remote execution of commands, forwarded
+ TCP/IP connections, and forwarded X11 connections. The service name
+ for this protocol is "ssh-connection".
+
+ This document should be read only after reading the SSH architecture
+ document [SSH-ARCH]. This document freely uses terminology and
+ notation from the architecture document without reference or further
+ explanation.
+
+3. Conventions Used in This Document
+
+ The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ and "MAY" that appear in this document are to be interpreted as
+ described in [RFC2119].
+
+ The used data types and terminology are specified in the architecture
+ document [SSH-ARCH].
+
+ The architecture document also discusses the algorithm naming
+ conventions that MUST be used with the SSH protocols.
+
+4. Global Requests
+
+ There are several kinds of requests that affect the state of the
+ remote end "globally", independent of any channels. An example is a
+ request to start TCP/IP forwarding for a specific port. All such
+ requests use the following format.
+
+ byte SSH_MSG_GLOBAL_REQUEST
+ string request name (restricted to US-ASCII)
+ boolean want reply
+ ... request-specific data follows
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ Request names follow the DNS extensibility naming convention outlined
+ in [SSH-ARCH].
+
+ The recipient will respond to this message with
+ SSH_MSG_REQUEST_SUCCESS or SSH_MSG_REQUEST_FAILURE if `want reply' is
+ TRUE.
+
+ byte SSH_MSG_REQUEST_SUCCESS
+ ..... response specific data
+
+ Usually the response specific data is non-existent.
+
+ If the recipient does not recognize or support the request, it simply
+ responds with SSH_MSG_REQUEST_FAILURE.
+
+ byte SSH_MSG_REQUEST_FAILURE
+
+
+5. Channel Mechanism
+
+ All terminal sessions, forwarded connections, etc. are channels.
+ Either side may open a channel. Multiple channels are multiplexed
+ into a single connection.
+
+ Channels are identified by numbers at each end. The number referring
+ to a channel may be different on each side. Requests to open a
+ channel contain the sender's channel number. Any other
+ channel-related messages contain the recipient's channel number for
+ the channel.
+
+ Channels are flow-controlled. No data may be sent to a channel until
+ a message is received to indicate that window space is available.
+
+5.1 Opening a Channel
+
+ When either side wishes to open a new channel, it allocates a local
+ number for the channel. It then sends the following message to the
+ other side, and includes the local channel number and initial window
+ size in the message.
+
+ byte SSH_MSG_CHANNEL_OPEN
+ string channel type (restricted to US-ASCII)
+ uint32 sender channel
+ uint32 initial window size
+ uint32 maximum packet size
+ ... channel type specific data follows
+
+ The channel type is a name as described in the SSH architecture
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ document, with similar extension mechanisms. `sender channel' is a
+ local identifier for the channel used by the sender of this message.
+ `initial window size' specifies how many bytes of channel data can be
+ sent to the sender of this message without adjusting the window.
+ `Maximum packet size' specifies the maximum size of an individual
+ data packet that can be sent to the sender (for example, one might
+ want to use smaller packets for interactive connections to get better
+ interactive response on slow links).
+
+ The remote side then decides whether it can open the channel, and
+ responds with either
+
+ byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+ uint32 recipient channel
+ uint32 sender channel
+ uint32 initial window size
+ uint32 maximum packet size
+ ... channel type specific data follows
+
+ where `recipient channel' is the channel number given in the original
+ open request, and `sender channel' is the channel number allocated by
+ the other side, or
+
+ byte SSH_MSG_CHANNEL_OPEN_FAILURE
+ uint32 recipient channel
+ uint32 reason code
+ string additional textual information (ISO-10646 UTF-8 [RFC2279])
+ string language tag (as defined in [RFC3066])
+
+ If the recipient of the SSH_MSG_CHANNEL_OPEN message does not support
+ the specified channel type, it simply responds with
+ SSH_MSG_CHANNEL_OPEN_FAILURE. The client MAY show the additional
+ information to the user. If this is done, the client software should
+ take the precautions discussed in [SSH-ARCH].
+
+ The following reason codes are defined:
+
+ #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
+ #define SSH_OPEN_CONNECT_FAILED 2
+ #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
+ #define SSH_OPEN_RESOURCE_SHORTAGE 4
+
+
+5.2 Data Transfer
+
+ The window size specifies how many bytes the other party can send
+ before it must wait for the window to be adjusted. Both parties use
+ the following message to adjust the window.
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ byte SSH_MSG_CHANNEL_WINDOW_ADJUST
+ uint32 recipient channel
+ uint32 bytes to add
+
+ After receiving this message, the recipient MAY send the given number
+ of bytes more than it was previously allowed to send; the window size
+ is incremented.
+
+ Data transfer is done with messages of the following type.
+
+ byte SSH_MSG_CHANNEL_DATA
+ uint32 recipient channel
+ string data
+
+ The maximum amount of data allowed is the current window size. The
+ window size is decremented by the amount of data sent. Both parties
+ MAY ignore all extra data sent after the allowed window is empty.
+
+ Additionally, some channels can transfer several types of data. An
+ example of this is stderr data from interactive sessions. Such data
+ can be passed with SSH_MSG_CHANNEL_EXTENDED_DATA messages, where a
+ separate integer specifies the type of the data. The available types
+ and their interpretation depend on the type of the channel.
+
+ byte SSH_MSG_CHANNEL_EXTENDED_DATA
+ uint32 recipient_channel
+ uint32 data_type_code
+ string data
+
+ Data sent with these messages consumes the same window as ordinary
+ data.
+
+ Currently, only the following type is defined.
+
+ #define SSH_EXTENDED_DATA_STDERR 1
+
+
+5.3 Closing a Channel
+
+ When a party will no longer send more data to a channel, it SHOULD
+ send SSH_MSG_CHANNEL_EOF.
+
+ byte SSH_MSG_CHANNEL_EOF
+ uint32 recipient_channel
+
+ No explicit response is sent to this message; however, the
+ application may send EOF to whatever is at the other end of the
+ channel. Note that the channel remains open after this message, and
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ more data may still be sent in the other direction. This message
+ does not consume window space and can be sent even if no window space
+ is available.
+
+ When either party wishes to terminate the channel, it sends
+ SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST
+ send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this
+ message for the channel. The channel is considered closed for a
+ party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and
+ the party may then reuse the channel number. A party MAY send
+ SSH_MSG_CHANNEL_CLOSE without having sent or received
+ SSH_MSG_CHANNEL_EOF.
+
+ byte SSH_MSG_CHANNEL_CLOSE
+ uint32 recipient_channel
+
+ This message does not consume window space and can be sent even if no
+ window space is available.
+
+ It is recommended that any data sent before this message is delivered
+ to the actual destination, if possible.
+
+5.4 Channel-Specific Requests
+
+ Many channel types have extensions that are specific to that
+ particular channel type. An example is requesting a pty (pseudo
+ terminal) for an interactive session.
+
+ All channel-specific requests use the following format.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string request type (restricted to US-ASCII)
+ boolean want reply
+ ... type-specific data
+
+ If want reply is FALSE, no response will be sent to the request.
+ Otherwise, the recipient responds with either SSH_MSG_CHANNEL_SUCCESS
+ or SSH_MSG_CHANNEL_FAILURE, or request-specific continuation
+ messages. If the request is not recognized or is not supported for
+ the channel, SSH_MSG_CHANNEL_FAILURE is returned.
+
+ This message does not consume window space and can be sent even if no
+ window space is available. Request types are local to each channel
+ type.
+
+ The client is allowed to send further messages without waiting for
+ the response to the request.
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ request type names follow the DNS extensibility naming convention
+ outlined in [SSH-ARCH]
+
+ byte SSH_MSG_CHANNEL_SUCCESS
+ uint32 recipient_channel
+
+
+ byte SSH_MSG_CHANNEL_FAILURE
+ uint32 recipient_channel
+
+ These messages do not consume window space and can be sent even if no
+ window space is available.
+
+6. Interactive Sessions
+
+ A session is a remote execution of a program. The program may be a
+ shell, an application, a system command, or some built-in subsystem.
+ It may or may not have a tty, and may or may not involve X11
+ forwarding. Multiple sessions can be active simultaneously.
+
+6.1 Opening a Session
+
+ A session is started by sending the following message.
+
+ byte SSH_MSG_CHANNEL_OPEN
+ string "session"
+ uint32 sender channel
+ uint32 initial window size
+ uint32 maximum packet size
+
+ Client implementations SHOULD reject any session channel open
+ requests to make it more difficult for a corrupt server to attack the
+ client.
+
+6.2 Requesting a Pseudo-Terminal
+
+ A pseudo-terminal can be allocated for the session by sending the
+ following message.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient_channel
+ string "pty-req"
+ boolean want_reply
+ string TERM environment variable value (e.g., vt100)
+ uint32 terminal width, characters (e.g., 80)
+ uint32 terminal height, rows (e.g., 24)
+ uint32 terminal width, pixels (e.g., 640)
+ uint32 terminal height, pixels (e.g., 480)
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ string encoded terminal modes
+
+ The encoding of terminal modes is described in Section Encoding of
+ Terminal Modes (Section 8). Zero dimension parameters MUST be
+ ignored. The character/row dimensions override the pixel dimensions
+ (when nonzero). Pixel dimensions refer to the drawable area of the
+ window.
+
+ The dimension parameters are only informational.
+
+ The client SHOULD ignore pty requests.
+
+6.3 X11 Forwarding
+
+6.3.1 Requesting X11 Forwarding
+
+ X11 forwarding may be requested for a session by sending
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "x11-req"
+ boolean want reply
+ boolean single connection
+ string x11 authentication protocol
+ string x11 authentication cookie
+ uint32 x11 screen number
+
+ It is recommended that the authentication cookie that is sent be a
+ fake, random cookie, and that the cookie is checked and replaced by
+ the real cookie when a connection request is received.
+
+ X11 connection forwarding should stop when the session channel is
+ closed; however, already opened forwardings should not be
+ automatically closed when the session channel is closed.
+
+ If `single connection' is TRUE, only a single connection should be
+ forwarded. No more connections will be forwarded after the first, or
+ after the session channel has been closed.
+
+ The "x11 authentication protocol" is the name of the X11
+ authentication method used, e.g. "MIT-MAGIC-COOKIE-1".
+
+ The x11 authentication cookie MUST be hexadecimal encoded.
+
+ X Protocol is documented in [SCHEIFLER].
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+6.3.2 X11 Channels
+
+ X11 channels are opened with a channel open request. The resulting
+ channels are independent of the session, and closing the session
+ channel does not close the forwarded X11 channels.
+
+ byte SSH_MSG_CHANNEL_OPEN
+ string "x11"
+ uint32 sender channel
+ uint32 initial window size
+ uint32 maximum packet size
+ string originator address (e.g. "192.168.7.38")
+ uint32 originator port
+
+ The recipient should respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+ or SSH_MSG_CHANNEL_OPEN_FAILURE.
+
+ Implementations MUST reject any X11 channel open requests if they
+ have not requested X11 forwarding.
+
+6.4 Environment Variable Passing
+
+ Environment variables may be passed to the shell/command to be
+ started later. Uncontrolled setting of environment variables in a
+ privileged process can be a security hazard. It is recommended that
+ implementations either maintain a list of allowable variable names or
+ only set environment variables after the server process has dropped
+ sufficient privileges.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "env"
+ boolean want reply
+ string variable name
+ string variable value
+
+
+6.5 Starting a Shell or a Command
+
+ Once the session has been set up, a program is started at the remote
+ end. The program can be a shell, an application program or a
+ subsystem with a host-independent name. Only one of these requests
+ can succeed per channel.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "shell"
+ boolean want reply
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ This message will request the user's default shell (typically defined
+ in /etc/passwd in UNIX systems) to be started at the other end.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "exec"
+ boolean want reply
+ string command
+
+ This message will request the server to start the execution of the
+ given command. The command string may contain a path. Normal
+ precautions MUST be taken to prevent the execution of unauthorized
+ commands.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "subsystem"
+ boolean want reply
+ string subsystem name
+
+ This last form executes a predefined subsystem. It is expected that
+ these will include a general file transfer mechanism, and possibly
+ other features. Implementations may also allow configuring more such
+ mechanisms. As the user's shell is usually used to execute the
+ subsystem, it is advisable for the subsystem protocol to have a
+ "magic cookie" at the beginning of the protocol transaction to
+ distinguish it from arbitrary output generated by shell
+ initialization scripts etc. This spurious output from the shell may
+ be filtered out either at the server or at the client.
+
+ The server SHOULD not halt the execution of the protocol stack when
+ starting a shell or a program. All input and output from these SHOULD
+ be redirected to the channel or to the encrypted tunnel.
+
+ It is RECOMMENDED to request and check the reply for these messages.
+ The client SHOULD ignore these messages.
+
+ Subsystem names follow the DNS extensibility naming convention
+ outlined in [SSH-ARCH].
+
+6.6 Session Data Transfer
+
+ Data transfer for a session is done using SSH_MSG_CHANNEL_DATA and
+ SSH_MSG_CHANNEL_EXTENDED_DATA packets and the window mechanism. The
+ extended data type SSH_EXTENDED_DATA_STDERR has been defined for
+ stderr data.
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+6.7 Window Dimension Change Message
+
+ When the window (terminal) size changes on the client side, it MAY
+ send a message to the other side to inform it of the new dimensions.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient_channel
+ string "window-change"
+ boolean FALSE
+ uint32 terminal width, columns
+ uint32 terminal height, rows
+ uint32 terminal width, pixels
+ uint32 terminal height, pixels
+
+ No response SHOULD be sent to this message.
+
+6.8 Local Flow Control
+
+ On many systems, it is possible to determine if a pseudo-terminal is
+ using control-S/control-Q flow control. When flow control is
+ allowed, it is often desirable to do the flow control at the client
+ end to speed up responses to user requests. This is facilitated by
+ the following notification. Initially, the server is responsible for
+ flow control. (Here, again, client means the side originating the
+ session, and server means the other side.)
+
+ The message below is used by the server to inform the client when it
+ can or cannot perform flow control (control-S/control-Q processing).
+ If `client can do' is TRUE, the client is allowed to do flow control
+ using control-S and control-Q. The client MAY ignore this message.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "xon-xoff"
+ boolean FALSE
+ boolean client can do
+
+ No response is sent to this message.
+
+6.9 Signals
+
+ A signal can be delivered to the remote process/service using the
+ following message. Some systems may not implement signals, in which
+ case they SHOULD ignore this message.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "signal"
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ boolean FALSE
+ string signal name without the "SIG" prefix.
+
+ Signal names will be encoded as discussed in the "exit-signal"
+ SSH_MSG_CHANNEL_REQUEST.
+
+6.10 Returning Exit Status
+
+ When the command running at the other end terminates, the following
+ message can be sent to return the exit status of the command.
+ Returning the status is RECOMMENDED. No acknowledgment is sent for
+ this message. The channel needs to be closed with
+ SSH_MSG_CHANNEL_CLOSE after this message.
+
+ The client MAY ignore these messages.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient_channel
+ string "exit-status"
+ boolean FALSE
+ uint32 exit_status
+
+ The remote command may also terminate violently due to a signal.
+ Such a condition can be indicated by the following message. A zero
+ exit_status usually means that the command terminated successfully.
+
+ byte SSH_MSG_CHANNEL_REQUEST
+ uint32 recipient channel
+ string "exit-signal"
+ boolean FALSE
+ string signal name without the "SIG" prefix.
+ boolean core dumped
+ string error message (ISO-10646 UTF-8)
+ string language tag (as defined in [RFC3066])
+
+ The signal name is one of the following (these are from [POSIX])
+
+ ABRT
+ ALRM
+ FPE
+ HUP
+ ILL
+ INT
+ KILL
+ PIPE
+ QUIT
+ SEGV
+ TERM
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ USR1
+ USR2
+
+ Additional signal names MAY be sent in the format "sig-name@xyz",
+ where `sig-name' and `xyz' may be anything a particular implementor
+ wants (except the `@' sign). However, it is suggested that if a
+ `configure' script is used, the non-standard signal names it finds be
+ encoded as "[email protected]", where `SIG' is the signal name
+ without the "SIG" prefix, and `xyz' be the host type, as determined
+ by `config.guess'.
+
+ The `error message' contains an additional explanation of the error
+ message. The message may consist of multiple lines. The client
+ software MAY display this message to the user. If this is done, the
+ client software should take the precautions discussed in [SSH-ARCH].
+
+7. TCP/IP Port Forwarding
+
+7.1 Requesting Port Forwarding
+
+ A party need not explicitly request forwardings from its own end to
+ the other direction. However, if it wishes that connections to a
+ port on the other side be forwarded to the local side, it must
+ explicitly request this.
+
+
+ byte SSH_MSG_GLOBAL_REQUEST
+ string "tcpip-forward"
+ boolean want reply
+ string address to bind (e.g. "0.0.0.0")
+ uint32 port number to bind
+
+ `Address to bind' and `port number to bind' specify the IP address
+ and port to which the socket to be listened is bound. The address
+ should be "0.0.0.0" if connections are allowed from anywhere. (Note
+ that the client can still filter connections based on information
+ passed in the open request.)
+
+ Implementations should only allow forwarding privileged ports if the
+ user has been authenticated as a privileged user.
+
+ Client implementations SHOULD reject these messages; they are
+ normally only sent by the client.
+
+
+ If a client passes 0 as port number to bind and has want reply TRUE
+ then the server allocates the next available unprivileged port number
+ and replies with the following message, otherwise there is no
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ response specific data.
+
+
+ byte SSH_MSG_GLOBAL_REQUEST_SUCCESS
+ uint32 port that was bound on the server
+
+ A port forwarding can be cancelled with the following message. Note
+ that channel open requests may be received until a reply to this
+ message is received.
+
+ byte SSH_MSG_GLOBAL_REQUEST
+ string "cancel-tcpip-forward"
+ boolean want reply
+ string address_to_bind (e.g. "127.0.0.1")
+ uint32 port number to bind
+
+ Client implementations SHOULD reject these messages; they are
+ normally only sent by the client.
+
+7.2 TCP/IP Forwarding Channels
+
+ When a connection comes to a port for which remote forwarding has
+ been requested, a channel is opened to forward the port to the other
+ side.
+
+ byte SSH_MSG_CHANNEL_OPEN
+ string "forwarded-tcpip"
+ uint32 sender channel
+ uint32 initial window size
+ uint32 maximum packet size
+ string address that was connected
+ uint32 port that was connected
+ string originator IP address
+ uint32 originator port
+
+ Implementations MUST reject these messages unless they have
+ previously requested a remote TCP/IP port forwarding with the given
+ port number.
+
+ When a connection comes to a locally forwarded TCP/IP port, the
+ following packet is sent to the other side. Note that these messages
+ MAY be sent also for ports for which no forwarding has been
+ explicitly requested. The receiving side must decide whether to
+ allow the forwarding.
+
+ byte SSH_MSG_CHANNEL_OPEN
+ string "direct-tcpip"
+ uint32 sender channel
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ uint32 initial window size
+ uint32 maximum packet size
+ string host to connect
+ uint32 port to connect
+ string originator IP address
+ uint32 originator port
+
+ `Host to connect' and `port to connect' specify the TCP/IP host and
+ port where the recipient should connect the channel. `Host to
+ connect' may be either a domain name or a numeric IP address.
+
+ `Originator IP address' is the numeric IP address of the machine
+ where the connection request comes from, and `originator port' is the
+ port on the originator host from where the connection came from.
+
+ Forwarded TCP/IP channels are independent of any sessions, and
+ closing a session channel does not in any way imply that forwarded
+ connections should be closed.
+
+ Client implementations SHOULD reject direct TCP/IP open requests for
+ security reasons.
+
+8. Encoding of Terminal Modes
+
+ Terminal modes (as passed in a pty request) are encoded into a byte
+ stream. It is intended that the coding be portable across different
+ environments.
+
+ The tty mode description is a stream of bytes. The stream consists
+ of opcode-argument pairs. It is terminated by opcode TTY_OP_END (0).
+ Opcodes 1 to 159 have a single uint32 argument. Opcodes 160 to 255
+ are not yet defined, and cause parsing to stop (they should only be
+ used after any other data).
+
+ The client SHOULD put in the stream any modes it knows about, and the
+ server MAY ignore any modes it does not know about. This allows some
+ degree of machine-independence, at least between systems that use a
+ POSIX-like tty interface. The protocol can support other systems as
+ well, but the client may need to fill reasonable values for a number
+ of parameters so the server pty gets set to a reasonable mode (the
+ server leaves all unspecified mode bits in their default values, and
+ only some combinations make sense).
+
+ The following opcodes have been defined. The naming of opcodes
+ mostly follows the POSIX terminal mode flags.
+
+ 0 TTY_OP_END Indicates end of options.
+ 1 VINTR Interrupt character; 255 if none. Similarly for the
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ other characters. Not all of these characters are
+ supported on all systems.
+ 2 VQUIT The quit character (sends SIGQUIT signal on POSIX
+ systems).
+ 3 VERASE Erase the character to left of the cursor.
+ 4 VKILL Kill the current input line.
+ 5 VEOF End-of-file character (sends EOF from the terminal).
+ 6 VEOL End-of-line character in addition to carriage return
+ and/or linefeed.
+ 7 VEOL2 Additional end-of-line character.
+ 8 VSTART Continues paused output (normally control-Q).
+ 9 VSTOP Pauses output (normally control-S).
+ 10 VSUSP Suspends the current program.
+ 11 VDSUSP Another suspend character.
+ 12 VREPRINT Reprints the current input line.
+ 13 VWERASE Erases a word left of cursor.
+ 14 VLNEXT Enter the next character typed literally, even if it
+ is a special character
+ 15 VFLUSH Character to flush output.
+ 16 VSWTCH Switch to a different shell layer.
+ 17 VSTATUS Prints system status line (load, command, pid etc).
+ 18 VDISCARD Toggles the flushing of terminal output.
+ 30 IGNPAR The ignore parity flag. The parameter SHOULD be 0 if
+ this flag is FALSE set, and 1 if it is TRUE.
+ 31 PARMRK Mark parity and framing errors.
+ 32 INPCK Enable checking of parity errors.
+ 33 ISTRIP Strip 8th bit off characters.
+ 34 INLCR Map NL into CR on input.
+ 35 IGNCR Ignore CR on input.
+ 36 ICRNL Map CR to NL on input.
+ 37 IUCLC Translate uppercase characters to lowercase.
+ 38 IXON Enable output flow control.
+ 39 IXANY Any char will restart after stop.
+ 40 IXOFF Enable input flow control.
+ 41 IMAXBEL Ring bell on input queue full.
+ 50 ISIG Enable signals INTR, QUIT, [D]SUSP.
+ 51 ICANON Canonicalize input lines.
+ 52 XCASE Enable input and output of uppercase characters by
+ preceding their lowercase equivalents with `\'.
+ 53 ECHO Enable echoing.
+ 54 ECHOE Visually erase chars.
+ 55 ECHOK Kill character discards current line.
+ 56 ECHONL Echo NL even if ECHO is off.
+ 57 NOFLSH Don't flush after interrupt.
+ 58 TOSTOP Stop background jobs from output.
+ 59 IEXTEN Enable extensions.
+ 60 ECHOCTL Echo control characters as ^(Char).
+ 61 ECHOKE Visual erase for line kill.
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ 62 PENDIN Retype pending input.
+ 70 OPOST Enable output processing.
+ 71 OLCUC Convert lowercase to uppercase.
+ 72 ONLCR Map NL to CR-NL.
+ 73 OCRNL Translate carriage return to newline (output).
+ 74 ONOCR Translate newline to carriage return-newline
+ (output).
+ 75 ONLRET Newline performs a carriage return (output).
+ 90 CS7 7 bit mode.
+ 91 CS8 8 bit mode.
+ 92 PARENB Parity enable.
+ 93 PARODD Odd parity, else even.
+
+ 128 TTY_OP_ISPEED Specifies the input baud rate in bits per second.
+ 129 TTY_OP_OSPEED Specifies the output baud rate in bits per second.
+
+
+9. Summary of Message Numbers
+
+ #define SSH_MSG_GLOBAL_REQUEST 80
+ #define SSH_MSG_REQUEST_SUCCESS 81
+ #define SSH_MSG_REQUEST_FAILURE 82
+ #define SSH_MSG_CHANNEL_OPEN 90
+ #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
+ #define SSH_MSG_CHANNEL_OPEN_FAILURE 92
+ #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
+ #define SSH_MSG_CHANNEL_DATA 94
+ #define SSH_MSG_CHANNEL_EXTENDED_DATA 95
+ #define SSH_MSG_CHANNEL_EOF 96
+ #define SSH_MSG_CHANNEL_CLOSE 97
+ #define SSH_MSG_CHANNEL_REQUEST 98
+ #define SSH_MSG_CHANNEL_SUCCESS 99
+ #define SSH_MSG_CHANNEL_FAILURE 100
+
+
+10. Security Considerations
+
+ This protocol is assumed to run on top of a secure, authenticated
+ transport. User authentication and protection against network-level
+ attacks are assumed to be provided by the underlying protocols.
+
+ It is RECOMMENDED that implementations disable all the potentially
+ dangerous features (e.g. agent forwarding, X11 forwarding, and TCP/IP
+ forwarding) if the host key has changed.
+
+ Full security considerations for this protocol are provided in
+ Section 8 of [SSH-ARCH]
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+11. iana cONSiderations
+
+ This document is part of a set, the IANA considerations for the SSH
+ protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],
+ [SSH-CONNECT] are detailed in [SSH-NUMBERS].
+
+12. Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementers or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF has been notified of intellectual property rights claimed in
+ regard to some or all of the specification contained in this
+ document. For more information consult the online list of claimed
+ rights.
+
+Normative References
+
+ [SSH-ARCH]
+ Ylonen, T., "SSH Protocol Architecture", I-D
+ draft-ietf-architecture-15.txt, Oct 2003.
+
+ [SSH-TRANS]
+ Ylonen, T., "SSH Transport Layer Protocol", I-D
+ draft-ietf-transport-17.txt, Oct 2003.
+
+ [SSH-USERAUTH]
+ Ylonen, T., "SSH Authentication Protocol", I-D
+ draft-ietf-userauth-18.txt, Oct 2003.
+
+ [SSH-CONNECT]
+ Ylonen, T., "SSH Connection Protocol", I-D
+ draft-ietf-connect-18.txt, Oct 2003.
+
+ [SSH-NUMBERS]
+ Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
+ Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ 2003.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+Informative References
+
+ [RFC3066] Alvestrand, H., "Tags for the Identification of
+ Languages", BCP 47, RFC 3066, January 2001.
+
+ [RFC1884] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 1884, December 1995.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+ [SCHEIFLER]
+ Scheifler, R., "X Window System : The Complete Reference
+ to Xlib, X Protocol, Icccm, Xlfd, 3rd edition.", Digital
+ Press ISBN 1555580882, Feburary 1992.
+
+ [POSIX] ISO/IEC, 9945-1., "Information technology -- Portable
+ Operating System Interface (POSIX)-Part 1: System
+ Application Program Interface (API) C Language", ANSI/IEE
+ Std 1003.1, July 1996.
+
+
+Authors' Addresses
+
+ Tatu Ylonen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+ Darren J. Moffat (editor)
+ Sun Microsystems, Inc
+ 17 Network Circle
+ Menlo Park CA 94025
+ USA
+
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+ The IETF has been notified of intellectual property rights claimed in
+ regard to some or all of the specification contained in this
+ document. For more information consult the online list of claimed
+ rights.
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]
+
+Internet-Draft SSH Connection Protocol Oct 2003
+
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22] \ No newline at end of file
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps
new file mode 100644
index 0000000000..06c91bf8cd
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.2.ps
@@ -0,0 +1,2853 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 75 0 595 747
+%%Title: Enscript Output
+%%For: Magnus Thoang
+%%Creator: GNU enscript 1.6.1
+%%CreationDate: Wed Nov 12 12:26:07 2003
+%%Orientation: Portrait
+%%Pages: 15 0
+%%DocumentMedia: A4 595 842 0 () ()
+%%DocumentNeededResources: (atend)
+%%EndComments
+%%BeginProlog
+%%BeginProcSet: PStoPS 1 15
+userdict begin
+[/showpage/erasepage/copypage]{dup where{pop dup load
+ type/operatortype eq{1 array cvx dup 0 3 index cvx put
+ bind def}{pop}ifelse}{pop}ifelse}forall
+[/letter/legal/executivepage/a4/a4small/b5/com10envelope
+ /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
+ /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
+ {pop{}def}ifelse}{pop}ifelse}forall
+/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
+ {pop def}ifelse}{def}ifelse
+/PStoPSmatrix matrix currentmatrix def
+/PStoPSxform matrix def/PStoPSclip{clippath}def
+/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
+/initmatrix{matrix defaultmatrix setmatrix}bind def
+/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
+ [{currentpoint}stopped{$error/newerror false put{newpath}}
+ {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
+ {[/newpath cvx{/moveto cvx}{/lineto cvx}
+ {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
+ stopped{$error/errorname get/invalidaccess eq{cleartomark
+ $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
+ /initclip dup load dup type dup/operatortype eq{pop exch pop}
+ {dup/arraytype eq exch/packedarraytype eq or
+ {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
+ {pop cvx}ifelse}ifelse
+ {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
+/initgraphics{initmatrix newpath initclip 1 setlinewidth
+ 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
+ 10 setmiterlimit}bind def
+end
+%%EndProcSet
+%%BeginResource: procset Enscript-Prolog 1.6 1
+%
+% Procedures.
+%
+
+/_S { % save current state
+ /_s save def
+} def
+/_R { % restore from saved state
+ _s restore
+} def
+
+/S { % showpage protecting gstate
+ gsave
+ showpage
+ grestore
+} bind def
+
+/MF { % fontname newfontname -> - make a new encoded font
+ /newfontname exch def
+ /fontname exch def
+
+ /fontdict fontname findfont def
+ /newfont fontdict maxlength dict def
+
+ fontdict {
+ exch
+ dup /FID eq {
+ % skip FID pair
+ pop pop
+ } {
+ % copy to the new font dictionary
+ exch newfont 3 1 roll put
+ } ifelse
+ } forall
+
+ newfont /FontName newfontname put
+
+ % insert only valid encoding vectors
+ encoding_vector length 256 eq {
+ newfont /Encoding encoding_vector put
+ } if
+
+ newfontname newfont definefont pop
+} def
+
+/SF { % fontname width height -> - set a new font
+ /height exch def
+ /width exch def
+
+ findfont
+ [width 0 0 height 0 0] makefont setfont
+} def
+
+/SUF { % fontname width height -> - set a new user font
+ /height exch def
+ /width exch def
+
+ /F-gs-user-font MF
+ /F-gs-user-font width height SF
+} def
+
+/M {moveto} bind def
+/s {show} bind def
+
+/Box { % x y w h -> - define box path
+ /d_h exch def /d_w exch def /d_y exch def /d_x exch def
+ d_x d_y moveto
+ d_w 0 rlineto
+ 0 d_h rlineto
+ d_w neg 0 rlineto
+ closepath
+} def
+
+/bgs { % x y height blskip gray str -> - show string with bg color
+ /str exch def
+ /gray exch def
+ /blskip exch def
+ /height exch def
+ /y exch def
+ /x exch def
+
+ gsave
+ x y blskip sub str stringwidth pop height Box
+ gray setgray
+ fill
+ grestore
+ x y M str s
+} def
+
+% Highlight bars.
+/highlight_bars { % nlines lineheight output_y_margin gray -> -
+ gsave
+ setgray
+ /ymarg exch def
+ /lineheight exch def
+ /nlines exch def
+
+ % This 2 is just a magic number to sync highlight lines to text.
+ 0 d_header_y ymarg sub 2 sub translate
+
+ /cw d_output_w cols div def
+ /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
+
+ % for each column
+ 0 1 cols 1 sub {
+ cw mul /xp exch def
+
+ % for each rows
+ 0 1 nrows 1 sub {
+ /rn exch def
+ rn lineheight mul neg /yp exch def
+ rn nlines idiv 2 mod 0 eq {
+ % Draw highlight bar. 4 is just a magic indentation.
+ xp 4 add yp cw 8 sub lineheight neg Box fill
+ } if
+ } for
+ } for
+
+ grestore
+} def
+
+% Line highlight bar.
+/line_highlight { % x y width height gray -> -
+ gsave
+ /gray exch def
+ Box gray setgray fill
+ grestore
+} def
+
+% Column separator lines.
+/column_lines {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h translate
+ /cw d_output_w cols div def
+ 1 1 cols 1 sub {
+ cw mul 0 moveto
+ 0 d_output_h rlineto stroke
+ } for
+ grestore
+} def
+
+% Column borders.
+/column_borders {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h moveto
+ 0 d_output_h rlineto
+ d_output_w 0 rlineto
+ 0 d_output_h neg rlineto
+ closepath stroke
+ grestore
+} def
+
+% Do the actual underlay drawing
+/draw_underlay {
+ ul_style 0 eq {
+ ul_str true charpath stroke
+ } {
+ ul_str show
+ } ifelse
+} def
+
+% Underlay
+/underlay { % - -> -
+ gsave
+ 0 d_page_h translate
+ d_page_h neg d_page_w atan rotate
+
+ ul_gray setgray
+ ul_font setfont
+ /dw d_page_h dup mul d_page_w dup mul add sqrt def
+ ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
+ draw_underlay
+ grestore
+} def
+
+/user_underlay { % - -> -
+ gsave
+ ul_x ul_y translate
+ ul_angle rotate
+ ul_gray setgray
+ ul_font setfont
+ 0 0 ul_h_ptsize 2 div sub moveto
+ draw_underlay
+ grestore
+} def
+
+% Page prefeed
+/page_prefeed { % bool -> -
+ statusdict /prefeed known {
+ statusdict exch /prefeed exch put
+ } {
+ pop
+ } ifelse
+} def
+
+% Wrapped line markers
+/wrapped_line_mark { % x y charwith charheight type -> -
+ /type exch def
+ /h exch def
+ /w exch def
+ /y exch def
+ /x exch def
+
+ type 2 eq {
+ % Black boxes (like TeX does)
+ gsave
+ 0 setlinewidth
+ x w 4 div add y M
+ 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
+ closepath fill
+ grestore
+ } {
+ type 3 eq {
+ % Small arrows
+ gsave
+ .2 setlinewidth
+ x w 2 div add y h 2 div add M
+ w 4 div 0 rlineto
+ x w 4 div add y lineto stroke
+
+ x w 4 div add w 8 div add y h 4 div add M
+ x w 4 div add y lineto
+ w 4 div h 8 div rlineto stroke
+ grestore
+ } {
+ % do nothing
+ } ifelse
+ } ifelse
+} def
+
+% EPSF import.
+
+/BeginEPSF {
+ /b4_Inc_state save def % Save state for cleanup
+ /dict_count countdictstack def % Count objects on dict stack
+ /op_count count 1 sub def % Count objects on operand stack
+ userdict begin
+ /showpage { } def
+ 0 setgray 0 setlinecap
+ 1 setlinewidth 0 setlinejoin
+ 10 setmiterlimit [ ] 0 setdash newpath
+ /languagelevel where {
+ pop languagelevel
+ 1 ne {
+ false setstrokeadjust false setoverprint
+ } if
+ } if
+} bind def
+
+/EndEPSF {
+ count op_count sub { pos } repeat % Clean up stacks
+ countdictstack dict_count sub { end } repeat
+ b4_Inc_state restore
+} bind def
+
+% Check PostScript language level.
+/languagelevel where {
+ pop /gs_languagelevel languagelevel def
+} {
+ /gs_languagelevel 1 def
+} ifelse
+%%EndResource
+%%BeginResource: procset Enscript-Encoding-88591 1.6 1
+/encoding_vector [
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclam /quotedbl /numbersign
+/dollar /percent /ampersand /quoteright
+/parenleft /parenright /asterisk /plus
+/comma /hyphen /period /slash
+/zero /one /two /three
+/four /five /six /seven
+/eight /nine /colon /semicolon
+/less /equal /greater /question
+/at /A /B /C
+/D /E /F /G
+/H /I /J /K
+/L /M /N /O
+/P /Q /R /S
+/T /U /V /W
+/X /Y /Z /bracketleft
+/backslash /bracketright /asciicircum /underscore
+/quoteleft /a /b /c
+/d /e /f /g
+/h /i /j /k
+/l /m /n /o
+/p /q /r /s
+/t /u /v /w
+/x /y /z /braceleft
+/bar /braceright /tilde /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclamdown /cent /sterling
+/currency /yen /brokenbar /section
+/dieresis /copyright /ordfeminine /guillemotleft
+/logicalnot /hyphen /registered /macron
+/degree /plusminus /twosuperior /threesuperior
+/acute /mu /paragraph /bullet
+/cedilla /onesuperior /ordmasculine /guillemotright
+/onequarter /onehalf /threequarters /questiondown
+/Agrave /Aacute /Acircumflex /Atilde
+/Adieresis /Aring /AE /Ccedilla
+/Egrave /Eacute /Ecircumflex /Edieresis
+/Igrave /Iacute /Icircumflex /Idieresis
+/Eth /Ntilde /Ograve /Oacute
+/Ocircumflex /Otilde /Odieresis /multiply
+/Oslash /Ugrave /Uacute /Ucircumflex
+/Udieresis /Yacute /Thorn /germandbls
+/agrave /aacute /acircumflex /atilde
+/adieresis /aring /ae /ccedilla
+/egrave /eacute /ecircumflex /edieresis
+/igrave /iacute /icircumflex /idieresis
+/eth /ntilde /ograve /oacute
+/ocircumflex /otilde /odieresis /divide
+/oslash /ugrave /uacute /ucircumflex
+/udieresis /yacute /thorn /ydieresis
+] def
+%%EndResource
+%%EndProlog
+%%BeginSetup
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier
+/HFpt_w 10 def
+/HFpt_h 10 def
+/Courier-Bold /HF-gs-font MF
+/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
+/Courier /F-gs-font MF
+/F-gs-font 10 10 SF
+/#copies 1 def
+/d_page_w 520 def
+/d_page_h 747 def
+/d_header_x 0 def
+/d_header_y 747 def
+/d_header_w 520 def
+/d_header_h 0 def
+/d_footer_x 0 def
+/d_footer_y 0 def
+/d_footer_w 520 def
+/d_footer_h 0 def
+/d_output_w 520 def
+/d_output_h 747 def
+/cols 1 def
+userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
+ matrix invertmatrix matrix concatmatrix
+ matrix invertmatrix put
+%%EndSetup
+%%Page: (0,1) 1
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 1 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 701 M
+(Network Working Group T. Ylonen) s
+5 690 M
+(Internet-Draft S. Lehtinen) s
+5 679 M
+(Expires: April 1, 2002 SSH Communications Security Corp) s
+5 668 M
+( October 2001) s
+5 635 M
+( SSH File Transfer Protocol) s
+5 624 M
+( draft-ietf-secsh-filexfer-02.txt) s
+5 602 M
+(Status of this Memo) s
+5 580 M
+( This document is an Internet-Draft and is in full conformance with) s
+5 569 M
+( all provisions of Section 10 of RFC2026.) s
+5 547 M
+( Internet-Drafts are working documents of the Internet Engineering) s
+5 536 M
+( Task Force \(IETF\), its areas, and its working groups. Note that) s
+5 525 M
+( other groups may also distribute working documents as Internet-) s
+5 514 M
+( Drafts.) s
+5 492 M
+( Internet-Drafts are draft documents valid for a maximum of six months) s
+5 481 M
+( and may be updated, replaced, or obsoleted by other documents at any) s
+5 470 M
+( time. It is inappropriate to use Internet-Drafts as reference) s
+5 459 M
+( material or to cite them other than as "work in progress.") s
+5 437 M
+( The list of current Internet-Drafts can be accessed at http://) s
+5 426 M
+( www.ietf.org/ietf/1id-abstracts.txt.) s
+5 404 M
+( The list of Internet-Draft Shadow Directories can be accessed at) s
+5 393 M
+( http://www.ietf.org/shadow.html.) s
+5 371 M
+( This Internet-Draft will expire on April 1, 2002.) s
+5 349 M
+(Copyright Notice) s
+5 327 M
+( Copyright \(C\) The Internet Society \(2001\). All Rights Reserved.) s
+5 305 M
+(Abstract) s
+5 283 M
+( The SSH File Transfer Protocol provides secure file transfer) s
+5 272 M
+( functionality over any reliable data stream. It is the standard file) s
+5 261 M
+( transfer protocol for use with the SSH2 protocol. This document) s
+5 250 M
+( describes the file transfer protocol and its interface to the SSH2) s
+5 239 M
+( protocol suite.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 1]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 2 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(Table of Contents) s
+5 668 M
+( 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 657 M
+( 2. Use with the SSH Connection Protocol . . . . . . . . . . . . 4) s
+5 646 M
+( 3. General Packet Format . . . . . . . . . . . . . . . . . . . 5) s
+5 635 M
+( 4. Protocol Initialization . . . . . . . . . . . . . . . . . . 7) s
+5 624 M
+( 5. File Attributes . . . . . . . . . . . . . . . . . . . . . . 8) s
+5 613 M
+( 6. Requests From the Client to the Server . . . . . . . . . . . 10) s
+5 602 M
+( 6.1 Request Synchronization and Reordering . . . . . . . . . . . 10) s
+5 591 M
+( 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . . 11) s
+5 580 M
+( 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . . 11) s
+5 569 M
+( 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . . 13) s
+5 558 M
+( 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . . 14) s
+5 547 M
+( 6.6 Creating and Deleting Directories . . . . . . . . . . . . . 15) s
+5 536 M
+( 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . . 15) s
+5 525 M
+( 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . . 16) s
+5 514 M
+( 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . . 17) s
+5 503 M
+( 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . . 18) s
+5 492 M
+( 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . . 18) s
+5 481 M
+( 7. Responses from the Server to the Client . . . . . . . . . . 20) s
+5 470 M
+( 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . . 24) s
+5 459 M
+( 9. Security Considerations . . . . . . . . . . . . . . . . . . 25) s
+5 448 M
+( 10. Changes from previous protocol versions . . . . . . . . . . 26) s
+5 437 M
+( 10.1 Changes between versions 3 and 2 . . . . . . . . . . . . . . 26) s
+5 426 M
+( 10.2 Changes between versions 2 and 1 . . . . . . . . . . . . . . 26) s
+5 415 M
+( 10.3 Changes between versions 1 and 0 . . . . . . . . . . . . . . 26) s
+5 404 M
+( 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . . 27) s
+5 393 M
+( References . . . . . . . . . . . . . . . . . . . . . . . . . 28) s
+5 382 M
+( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 28) s
+5 371 M
+( Full Copyright Statement . . . . . . . . . . . . . . . . . . 29) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 2]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (2,3) 2
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 3 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(1. Introduction) s
+5 668 M
+( This protocol provides secure file transfer \(and more generally file) s
+5 657 M
+( system access\) functionality over a reliable data stream, such as a) s
+5 646 M
+( channel in the SSH2 protocol [3].) s
+5 624 M
+( This protocol is designed so that it could be used to implement a) s
+5 613 M
+( secure remote file system service, as well as a secure file transfer) s
+5 602 M
+( service.) s
+5 580 M
+( This protocol assumes that it runs over a secure channel, and that) s
+5 569 M
+( the server has already authenticated the user at the client end, and) s
+5 558 M
+( that the identity of the client user is externally available to the) s
+5 547 M
+( server implementation.) s
+5 525 M
+( In general, this protocol follows a simple request-response model.) s
+5 514 M
+( Each request and response contains a sequence number and multiple) s
+5 503 M
+( requests may be pending simultaneously. There are a relatively large) s
+5 492 M
+( number of different request messages, but a small number of possible) s
+5 481 M
+( response messages. Each request has one or more response messages) s
+5 470 M
+( that may be returned in result \(e.g., a read either returns data or) s
+5 459 M
+( reports error status\).) s
+5 437 M
+( The packet format descriptions in this specification follow the) s
+5 426 M
+( notation presented in the secsh architecture draft.[3].) s
+5 404 M
+( Even though this protocol is described in the context of the SSH2) s
+5 393 M
+( protocol, this protocol is general and independent of the rest of the) s
+5 382 M
+( SSH2 protocol suite. It could be used in a number of different) s
+5 371 M
+( applications, such as secure file transfer over TLS RFC 2246 [1] and) s
+5 360 M
+( transfer of management information in VPN applications.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 3]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 4 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(2. Use with the SSH Connection Protocol) s
+5 668 M
+( When used with the SSH2 Protocol suite, this protocol is intended to) s
+5 657 M
+( be used from the SSH Connection Protocol [5] as a subsystem, as) s
+5 646 M
+( described in section ``Starting a Shell or a Command''. The) s
+5 635 M
+( subsystem name used with this protocol is "sftp".) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 4]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (4,5) 3
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 5 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(3. General Packet Format) s
+5 668 M
+( All packets transmitted over the secure connection are of the) s
+5 657 M
+( following format:) s
+5 635 M
+( uint32 length) s
+5 624 M
+( byte type) s
+5 613 M
+( byte[length - 1] data payload) s
+5 591 M
+( That is, they are just data preceded by 32-bit length and 8-bit type) s
+5 580 M
+( fields. The `length' is the length of the data area, and does not) s
+5 569 M
+( include the `length' field itself. The format and interpretation of) s
+5 558 M
+( the data area depends on the packet type.) s
+5 536 M
+( All packet descriptions below only specify the packet type and the) s
+5 525 M
+( data that goes into the data field. Thus, they should be prefixed by) s
+5 514 M
+( the `length' and `type' fields.) s
+5 492 M
+( The maximum size of a packet is in practice determined by the client) s
+5 481 M
+( \(the maximum size of read or write requests that it sends, plus a few) s
+5 470 M
+( bytes of packet overhead\). All servers SHOULD support packets of at) s
+5 459 M
+( least 34000 bytes \(where the packet size refers to the full length,) s
+5 448 M
+( including the header above\). This should allow for reads and writes) s
+5 437 M
+( of at most 32768 bytes.) s
+5 415 M
+( There is no limit on the number of outstanding \(non-acknowledged\)) s
+5 404 M
+( requests that the client may send to the server. In practice this is) s
+5 393 M
+( limited by the buffering available on the data stream and the queuing) s
+5 382 M
+( performed by the server. If the server's queues are full, it should) s
+5 371 M
+( not read any more data from the stream, and flow control will prevent) s
+5 360 M
+( the client from sending more requests. Note, however, that while) s
+5 349 M
+( there is no restriction on the protocol level, the client's API may) s
+5 338 M
+( provide a limit in order to prevent infinite queuing of outgoing) s
+5 327 M
+( requests at the client.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 5]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 6 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( The following values are defined for packet types.) s
+5 668 M
+( #define SSH_FXP_INIT 1) s
+5 657 M
+( #define SSH_FXP_VERSION 2) s
+5 646 M
+( #define SSH_FXP_OPEN 3) s
+5 635 M
+( #define SSH_FXP_CLOSE 4) s
+5 624 M
+( #define SSH_FXP_READ 5) s
+5 613 M
+( #define SSH_FXP_WRITE 6) s
+5 602 M
+( #define SSH_FXP_LSTAT 7) s
+5 591 M
+( #define SSH_FXP_FSTAT 8) s
+5 580 M
+( #define SSH_FXP_SETSTAT 9) s
+5 569 M
+( #define SSH_FXP_FSETSTAT 10) s
+5 558 M
+( #define SSH_FXP_OPENDIR 11) s
+5 547 M
+( #define SSH_FXP_READDIR 12) s
+5 536 M
+( #define SSH_FXP_REMOVE 13) s
+5 525 M
+( #define SSH_FXP_MKDIR 14) s
+5 514 M
+( #define SSH_FXP_RMDIR 15) s
+5 503 M
+( #define SSH_FXP_REALPATH 16) s
+5 492 M
+( #define SSH_FXP_STAT 17) s
+5 481 M
+( #define SSH_FXP_RENAME 18) s
+5 470 M
+( #define SSH_FXP_READLINK 19) s
+5 459 M
+( #define SSH_FXP_SYMLINK 20) s
+5 448 M
+( #define SSH_FXP_STATUS 101) s
+5 437 M
+( #define SSH_FXP_HANDLE 102) s
+5 426 M
+( #define SSH_FXP_DATA 103) s
+5 415 M
+( #define SSH_FXP_NAME 104) s
+5 404 M
+( #define SSH_FXP_ATTRS 105) s
+5 393 M
+( #define SSH_FXP_EXTENDED 200) s
+5 382 M
+( #define SSH_FXP_EXTENDED_REPLY 201) s
+5 360 M
+( Additional packet types should only be defined if the protocol) s
+5 349 M
+( version number \(see Section ``Protocol Initialization''\) is) s
+5 338 M
+( incremented, and their use MUST be negotiated using the version) s
+5 327 M
+( number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY) s
+5 316 M
+( packets can be used to implement vendor-specific extensions. See) s
+5 305 M
+( Section ``Vendor-Specific-Extensions'' for more details.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 6]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (6,7) 4
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 7 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(4. Protocol Initialization) s
+5 668 M
+( When the file transfer protocol starts, it first sends a SSH_FXP_INIT) s
+5 657 M
+( \(including its version number\) packet to the server. The server) s
+5 646 M
+( responds with a SSH_FXP_VERSION packet, supplying the lowest of its) s
+5 635 M
+( own and the client's version number. Both parties should from then) s
+5 624 M
+( on adhere to particular version of the protocol.) s
+5 602 M
+( The SSH_FXP_INIT packet \(from client to server\) has the following) s
+5 591 M
+( data:) s
+5 569 M
+( uint32 version) s
+5 558 M
+( <extension data>) s
+5 536 M
+( The SSH_FXP_VERSION packet \(from server to client\) has the following) s
+5 525 M
+( data:) s
+5 503 M
+( uint32 version) s
+5 492 M
+( <extension data>) s
+5 470 M
+( The version number of the protocol specified in this document is 3.) s
+5 459 M
+( The version number should be incremented for each incompatible) s
+5 448 M
+( revision of this protocol.) s
+5 426 M
+( The extension data in the above packets may be empty, or may be a) s
+5 415 M
+( sequence of) s
+5 393 M
+( string extension_name) s
+5 382 M
+( string extension_data) s
+5 360 M
+( pairs \(both strings MUST always be present if one is, but the) s
+5 349 M
+( `extension_data' string may be of zero length\). If present, these) s
+5 338 M
+( strings indicate extensions to the baseline protocol. The) s
+5 327 M
+( `extension_name' field\(s\) identify the name of the extension. The) s
+5 316 M
+( name should be of the form "name@domain", where the domain is the DNS) s
+5 305 M
+( domain name of the organization defining the extension. Additional) s
+5 294 M
+( names that are not of this format may be defined later by the IETF.) s
+5 283 M
+( Implementations MUST silently ignore any extensions whose name they) s
+5 272 M
+( do not recognize.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 7]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 8 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(5. File Attributes) s
+5 668 M
+( A new compound data type is defined for encoding file attributes. It) s
+5 657 M
+( is basically just a combination of elementary types, but is defined) s
+5 646 M
+( once because of the non-trivial description of the fields and to) s
+5 635 M
+( ensure maintainability.) s
+5 613 M
+( The same encoding is used both when returning file attributes from) s
+5 602 M
+( the server and when sending file attributes to the server. When) s
+5 591 M
+( sending it to the server, the flags field specifies which attributes) s
+5 580 M
+( are included, and the server will use default values for the) s
+5 569 M
+( remaining attributes \(or will not modify the values of remaining) s
+5 558 M
+( attributes\). When receiving attributes from the server, the flags) s
+5 547 M
+( specify which attributes are included in the returned data. The) s
+5 536 M
+( server normally returns all attributes it knows about.) s
+5 514 M
+( uint32 flags) s
+5 503 M
+( uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE) s
+5 492 M
+( uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID) s
+5 481 M
+( uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID) s
+5 470 M
+( uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS) s
+5 459 M
+( uint32 atime present only if flag SSH_FILEXFER_ACMODTIME) s
+5 448 M
+( uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME) s
+5 437 M
+( uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED) s
+5 426 M
+( string extended_type) s
+5 415 M
+( string extended_data) s
+5 404 M
+( ... more extended data \(extended_type - extended_data pairs\),) s
+5 393 M
+( so that number of pairs equals extended_count) s
+5 371 M
+( The `flags' specify which of the fields are present. Those fields) s
+5 360 M
+( for which the corresponding flag is not set are not present \(not) s
+5 349 M
+( included in the packet\). New flags can only be added by incrementing) s
+5 338 M
+( the protocol version number \(or by using the extension mechanism) s
+5 327 M
+( described below\).) s
+5 305 M
+( The `size' field specifies the size of the file in bytes.) s
+5 283 M
+( The `uid' and `gid' fields contain numeric Unix-like user and group) s
+5 272 M
+( identifiers, respectively.) s
+5 250 M
+( The `permissions' field contains a bit mask of file permissions as) s
+5 239 M
+( defined by posix [1].) s
+5 217 M
+( The `atime' and `mtime' contain the access and modification times of) s
+5 206 M
+( the files, respectively. They are represented as seconds from Jan 1,) s
+5 195 M
+( 1970 in UTC.) s
+5 173 M
+( The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 8]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (8,9) 5
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 9 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( mechanism for vendor-specific extensions. If the flag is specified,) s
+5 679 M
+( then the `extended_count' field is present. It specifies the number) s
+5 668 M
+( of extended_type-extended_data pairs that follow. Each of these) s
+5 657 M
+( pairs specifies an extended attribute. For each of the attributes,) s
+5 646 M
+( the extended_type field should be a string of the format) s
+5 635 M
+( "name@domain", where "domain" is a valid, registered domain name and) s
+5 624 M
+( "name" identifies the method. The IETF may later standardize certain) s
+5 613 M
+( names that deviate from this format \(e.g., that do not contain the) s
+5 602 M
+( "@" sign\). The interpretation of `extended_data' depends on the) s
+5 591 M
+( type. Implementations SHOULD ignore extended data fields that they) s
+5 580 M
+( do not understand.) s
+5 558 M
+( Additional fields can be added to the attributes by either defining) s
+5 547 M
+( additional bits to the flags field to indicate their presence, or by) s
+5 536 M
+( defining extended attributes for them. The extended attributes) s
+5 525 M
+( mechanism is recommended for most purposes; additional flags bits) s
+5 514 M
+( should only be defined by an IETF standards action that also) s
+5 503 M
+( increments the protocol version number. The use of such new fields) s
+5 492 M
+( MUST be negotiated by the version number in the protocol exchange.) s
+5 481 M
+( It is a protocol error if a packet with unsupported protocol bits is) s
+5 470 M
+( received.) s
+5 448 M
+( The flags bits are defined to have the following values:) s
+5 426 M
+( #define SSH_FILEXFER_ATTR_SIZE 0x00000001) s
+5 415 M
+( #define SSH_FILEXFER_ATTR_UIDGID 0x00000002) s
+5 404 M
+( #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004) s
+5 393 M
+( #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008) s
+5 382 M
+( #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 9]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 10 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(6. Requests From the Client to the Server) s
+5 668 M
+( Requests from the client to the server represent the various file) s
+5 657 M
+( system operations. Each request begins with an `id' field, which is) s
+5 646 M
+( a 32-bit identifier identifying the request \(selected by the client\).) s
+5 635 M
+( The same identifier will be returned in the response to the request.) s
+5 624 M
+( One possible implementation of it is a monotonically increasing) s
+5 613 M
+( request sequence number \(modulo 2^32\).) s
+5 591 M
+( Many operations in the protocol operate on open files. The) s
+5 580 M
+( SSH_FXP_OPEN request can return a file handle \(which is an opaque) s
+5 569 M
+( variable-length string\) which may be used to access the file later) s
+5 558 M
+( \(e.g. in a read operation\). The client MUST NOT send requests the) s
+5 547 M
+( server with bogus or closed handles. However, the server MUST) s
+5 536 M
+( perform adequate checks on the handle in order to avoid security) s
+5 525 M
+( risks due to fabricated handles.) s
+5 503 M
+( This design allows either stateful and stateless server) s
+5 492 M
+( implementation, as well as an implementation which caches state) s
+5 481 M
+( between requests but may also flush it. The contents of the file) s
+5 470 M
+( handle string are entirely up to the server and its design. The) s
+5 459 M
+( client should not modify or attempt to interpret the file handle) s
+5 448 M
+( strings.) s
+5 426 M
+( The file handle strings MUST NOT be longer than 256 bytes.) s
+5 404 M
+(6.1 Request Synchronization and Reordering) s
+5 382 M
+( The protocol and implementations MUST process requests relating to) s
+5 371 M
+( the same file in the order in which they are received. In other) s
+5 360 M
+( words, if an application submits multiple requests to the server, the) s
+5 349 M
+( results in the responses will be the same as if it had sent the) s
+5 338 M
+( requests one at a time and waited for the response in each case. For) s
+5 327 M
+( example, the server may process non-overlapping read/write requests) s
+5 316 M
+( to the same file in parallel, but overlapping reads and writes cannot) s
+5 305 M
+( be reordered or parallelized. However, there are no ordering) s
+5 294 M
+( restrictions on the server for processing requests from two different) s
+5 283 M
+( file transfer connections. The server may interleave and parallelize) s
+5 272 M
+( them at will.) s
+5 250 M
+( There are no restrictions on the order in which responses to) s
+5 239 M
+( outstanding requests are delivered to the client, except that the) s
+5 228 M
+( server must ensure fairness in the sense that processing of no) s
+5 217 M
+( request will be indefinitely delayed even if the client is sending) s
+5 206 M
+( other requests so that there are multiple outstanding requests all) s
+5 195 M
+( the time.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 10]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (10,11) 6
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 11 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(6.2 File Names) s
+5 668 M
+( This protocol represents file names as strings. File names are) s
+5 657 M
+( assumed to use the slash \('/'\) character as a directory separator.) s
+5 635 M
+( File names starting with a slash are "absolute", and are relative to) s
+5 624 M
+( the root of the file system. Names starting with any other character) s
+5 613 M
+( are relative to the user's default directory \(home directory\). Note) s
+5 602 M
+( that identifying the user is assumed to take place outside of this) s
+5 591 M
+( protocol.) s
+5 569 M
+( Servers SHOULD interpret a path name component ".." as referring to) s
+5 558 M
+( the parent directory, and "." as referring to the current directory.) s
+5 547 M
+( If the server implementation limits access to certain parts of the) s
+5 536 M
+( file system, it must be extra careful in parsing file names when) s
+5 525 M
+( enforcing such restrictions. There have been numerous reported) s
+5 514 M
+( security bugs where a ".." in a path name has allowed access outside) s
+5 503 M
+( the intended area.) s
+5 481 M
+( An empty path name is valid, and it refers to the user's default) s
+5 470 M
+( directory \(usually the user's home directory\).) s
+5 448 M
+( Otherwise, no syntax is defined for file names by this specification.) s
+5 437 M
+( Clients should not make any other assumptions; however, they can) s
+5 426 M
+( splice path name components returned by SSH_FXP_READDIR together) s
+5 415 M
+( using a slash \('/'\) as the separator, and that will work as expected.) s
+5 393 M
+( It is understood that the lack of well-defined semantics for file) s
+5 382 M
+( names may cause interoperability problems between clients and servers) s
+5 371 M
+( using radically different operating systems. However, this approach) s
+5 360 M
+( is known to work acceptably with most systems, and alternative) s
+5 349 M
+( approaches that e.g. treat file names as sequences of structured) s
+5 338 M
+( components are quite complicated.) s
+5 316 M
+(6.3 Opening, Creating, and Closing Files) s
+5 294 M
+( Files are opened and created using the SSH_FXP_OPEN message, whose) s
+5 283 M
+( data part is as follows:) s
+5 261 M
+( uint32 id) s
+5 250 M
+( string filename) s
+5 239 M
+( uint32 pflags) s
+5 228 M
+( ATTRS attrs) s
+5 206 M
+( The `id' field is the request identifier as for all requests.) s
+5 184 M
+( The `filename' field specifies the file name. See Section ``File) s
+5 173 M
+( Names'' for more information.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 11]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 12 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( The `pflags' field is a bitmask. The following bits have been) s
+5 679 M
+( defined.) s
+5 657 M
+( #define SSH_FXF_READ 0x00000001) s
+5 646 M
+( #define SSH_FXF_WRITE 0x00000002) s
+5 635 M
+( #define SSH_FXF_APPEND 0x00000004) s
+5 624 M
+( #define SSH_FXF_CREAT 0x00000008) s
+5 613 M
+( #define SSH_FXF_TRUNC 0x00000010) s
+5 602 M
+( #define SSH_FXF_EXCL 0x00000020) s
+5 580 M
+( These have the following meanings:) s
+5 558 M
+( SSH_FXF_READ) s
+5 547 M
+( Open the file for reading.) s
+5 525 M
+( SSH_FXF_WRITE) s
+5 514 M
+( Open the file for writing. If both this and SSH_FXF_READ are) s
+5 503 M
+( specified, the file is opened for both reading and writing.) s
+5 481 M
+( SSH_FXF_APPEND) s
+5 470 M
+( Force all writes to append data at the end of the file.) s
+5 448 M
+( SSH_FXF_CREAT) s
+5 437 M
+( If this flag is specified, then a new file will be created if one) s
+5 426 M
+( does not already exist \(if O_TRUNC is specified, the new file will) s
+5 415 M
+( be truncated to zero length if it previously exists\).) s
+5 393 M
+( SSH_FXF_TRUNC) s
+5 382 M
+( Forces an existing file with the same name to be truncated to zero) s
+5 371 M
+( length when creating a file by specifying SSH_FXF_CREAT.) s
+5 360 M
+( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
+5 338 M
+( SSH_FXF_EXCL) s
+5 327 M
+( Causes the request to fail if the named file already exists.) s
+5 316 M
+( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
+5 294 M
+( The `attrs' field specifies the initial attributes for the file.) s
+5 283 M
+( Default values will be used for those attributes that are not) s
+5 272 M
+( specified. See Section ``File Attributes'' for more information.) s
+5 250 M
+( Regardless the server operating system, the file will always be) s
+5 239 M
+( opened in "binary" mode \(i.e., no translations between different) s
+5 228 M
+( character sets and newline encodings\).) s
+5 206 M
+( The response to this message will be either SSH_FXP_HANDLE \(if the) s
+5 195 M
+( operation is successful\) or SSH_FXP_STATUS \(if the operation fails\).) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 12]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (12,13) 7
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 13 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( A file is closed by using the SSH_FXP_CLOSE request. Its data field) s
+5 679 M
+( has the following format:) s
+5 657 M
+( uint32 id) s
+5 646 M
+( string handle) s
+5 624 M
+( where `id' is the request identifier, and `handle' is a handle) s
+5 613 M
+( previously returned in the response to SSH_FXP_OPEN or) s
+5 602 M
+( SSH_FXP_OPENDIR. The handle becomes invalid immediately after this) s
+5 591 M
+( request has been sent.) s
+5 569 M
+( The response to this request will be a SSH_FXP_STATUS message. One) s
+5 558 M
+( should note that on some server platforms even a close can fail.) s
+5 547 M
+( This can happen e.g. if the server operating system caches writes,) s
+5 536 M
+( and an error occurs while flushing cached writes during the close.) s
+5 514 M
+(6.4 Reading and Writing) s
+5 492 M
+( Once a file has been opened, it can be read using the SSH_FXP_READ) s
+5 481 M
+( message, which has the following format:) s
+5 459 M
+( uint32 id) s
+5 448 M
+( string handle) s
+5 437 M
+( uint64 offset) s
+5 426 M
+( uint32 len) s
+5 404 M
+( where `id' is the request identifier, `handle' is an open file handle) s
+5 393 M
+( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) relative) s
+5 382 M
+( to the beginning of the file from where to start reading, and `len') s
+5 371 M
+( is the maximum number of bytes to read.) s
+5 349 M
+( In response to this request, the server will read as many bytes as it) s
+5 338 M
+( can from the file \(up to `len'\), and return them in a SSH_FXP_DATA) s
+5 327 M
+( message. If an error occurs or EOF is encountered before reading any) s
+5 316 M
+( data, the server will respond with SSH_FXP_STATUS. For normal disk) s
+5 305 M
+( files, it is guaranteed that this will read the specified number of) s
+5 294 M
+( bytes, or up to end of file. For e.g. device files this may return) s
+5 283 M
+( fewer bytes than requested.) s
+5 261 M
+( Writing to a file is achieved using the SSH_FXP_WRITE message, which) s
+5 250 M
+( has the following format:) s
+5 228 M
+( uint32 id) s
+5 217 M
+( string handle) s
+5 206 M
+( uint64 offset) s
+5 195 M
+( string data) s
+5 173 M
+( where `id' is a request identifier, `handle' is a file handle) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 13]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 14 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) from the) s
+5 679 M
+( beginning of the file where to start writing, and `data' is the data) s
+5 668 M
+( to be written.) s
+5 646 M
+( The write will extend the file if writing beyond the end of the file.) s
+5 635 M
+( It is legal to write way beyond the end of the file; the semantics) s
+5 624 M
+( are to write zeroes from the end of the file to the specified offset) s
+5 613 M
+( and then the data. On most operating systems, such writes do not) s
+5 602 M
+( allocate disk space but instead leave "holes" in the file.) s
+5 580 M
+( The server responds to a write request with a SSH_FXP_STATUS message.) s
+5 558 M
+(6.5 Removing and Renaming Files) s
+5 536 M
+( Files can be removed using the SSH_FXP_REMOVE message. It has the) s
+5 525 M
+( following format:) s
+5 503 M
+( uint32 id) s
+5 492 M
+( string filename) s
+5 470 M
+( where `id' is the request identifier and `filename' is the name of) s
+5 459 M
+( the file to be removed. See Section ``File Names'' for more) s
+5 448 M
+( information. This request cannot be used to remove directories.) s
+5 426 M
+( The server will respond to this request with a SSH_FXP_STATUS) s
+5 415 M
+( message.) s
+5 393 M
+( Files \(and directories\) can be renamed using the SSH_FXP_RENAME) s
+5 382 M
+( message. Its data is as follows:) s
+5 360 M
+( uint32 id) s
+5 349 M
+( string oldpath) s
+5 338 M
+( string newpath) s
+5 316 M
+( where `id' is the request identifier, `oldpath' is the name of an) s
+5 305 M
+( existing file or directory, and `newpath' is the new name for the) s
+5 294 M
+( file or directory. It is an error if there already exists a file) s
+5 283 M
+( with the name specified by newpath. The server may also fail rename) s
+5 272 M
+( requests in other situations, for example if `oldpath' and `newpath') s
+5 261 M
+( point to different file systems on the server.) s
+5 239 M
+( The server will respond to this request with a SSH_FXP_STATUS) s
+5 228 M
+( message.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 14]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (14,15) 8
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 15 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(6.6 Creating and Deleting Directories) s
+5 668 M
+( New directories can be created using the SSH_FXP_MKDIR request. It) s
+5 657 M
+( has the following format:) s
+5 635 M
+( uint32 id) s
+5 624 M
+( string path) s
+5 613 M
+( ATTRS attrs) s
+5 591 M
+( where `id' is the request identifier, `path' and `attrs' specifies) s
+5 580 M
+( the modifications to be made to its attributes. See Section ``File) s
+5 569 M
+( Names'' for more information on file names. Attributes are discussed) s
+5 558 M
+( in more detail in Section ``File Attributes''. specifies the) s
+5 547 M
+( directory to be created. An error will be returned if a file or) s
+5 536 M
+( directory with the specified path already exists. The server will) s
+5 525 M
+( respond to this request with a SSH_FXP_STATUS message.) s
+5 503 M
+( Directories can be removed using the SSH_FXP_RMDIR request, which) s
+5 492 M
+( has the following format:) s
+5 470 M
+( uint32 id) s
+5 459 M
+( string path) s
+5 437 M
+( where `id' is the request identifier, and `path' specifies the) s
+5 426 M
+( directory to be removed. See Section ``File Names'' for more) s
+5 415 M
+( information on file names. An error will be returned if no directory) s
+5 404 M
+( with the specified path exists, or if the specified directory is not) s
+5 393 M
+( empty, or if the path specified a file system object other than a) s
+5 382 M
+( directory. The server responds to this request with a SSH_FXP_STATUS) s
+5 371 M
+( message.) s
+5 349 M
+(6.7 Scanning Directories) s
+5 327 M
+( The files in a directory can be listed using the SSH_FXP_OPENDIR and) s
+5 316 M
+( SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one) s
+5 305 M
+( or more file names with full file attributes for each file. The) s
+5 294 M
+( client should call SSH_FXP_READDIR repeatedly until it has found the) s
+5 283 M
+( file it is looking for or until the server responds with a) s
+5 272 M
+( SSH_FXP_STATUS message indicating an error \(normally SSH_FX_EOF if) s
+5 261 M
+( there are no more files in the directory\). The client should then) s
+5 250 M
+( close the handle using the SSH_FXP_CLOSE request.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 15]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 16 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( The SSH_FXP_OPENDIR opens a directory for reading. It has the) s
+5 679 M
+( following format:) s
+5 657 M
+( uint32 id) s
+5 646 M
+( string path) s
+5 624 M
+( where `id' is the request identifier and `path' is the path name of) s
+5 613 M
+( the directory to be listed \(without any trailing slash\). See Section) s
+5 602 M
+( ``File Names'' for more information on file names. This will return) s
+5 591 M
+( an error if the path does not specify a directory or if the directory) s
+5 580 M
+( is not readable. The server will respond to this request with either) s
+5 569 M
+( a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.) s
+5 547 M
+( Once the directory has been successfully opened, files \(and) s
+5 536 M
+( directories\) contained in it can be listed using SSH_FXP_READDIR) s
+5 525 M
+( requests. These are of the format) s
+5 503 M
+( uint32 id) s
+5 492 M
+( string handle) s
+5 470 M
+( where `id' is the request identifier, and `handle' is a handle) s
+5 459 M
+( returned by SSH_FXP_OPENDIR. \(It is a protocol error to attempt to) s
+5 448 M
+( use an ordinary file handle returned by SSH_FXP_OPEN.\)) s
+5 426 M
+( The server responds to this request with either a SSH_FXP_NAME or a) s
+5 415 M
+( SSH_FXP_STATUS message. One or more names may be returned at a time.) s
+5 404 M
+( Full status information is returned for each name in order to speed) s
+5 393 M
+( up typical directory listings.) s
+5 371 M
+( When the client no longer wishes to read more names from the) s
+5 360 M
+( directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle) s
+5 349 M
+( should be closed regardless of whether an error has occurred or not.) s
+5 327 M
+(6.8 Retrieving File Attributes) s
+5 305 M
+( Very often, file attributes are automatically returned by) s
+5 294 M
+( SSH_FXP_READDIR. However, sometimes there is need to specifically) s
+5 283 M
+( retrieve the attributes for a named file. This can be done using the) s
+5 272 M
+( SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.) s
+5 250 M
+( SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT) s
+5 239 M
+( follows symbolic links on the server, whereas SSH_FXP_LSTAT does not) s
+5 228 M
+( follow symbolic links. Both have the same format:) s
+5 206 M
+( uint32 id) s
+5 195 M
+( string path) s
+5 173 M
+( where `id' is the request identifier, and `path' specifies the file) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 16]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (16,17) 9
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 17 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( system object for which status is to be returned. The server) s
+5 679 M
+( responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
+5 657 M
+( SSH_FXP_FSTAT differs from the others in that it returns status) s
+5 646 M
+( information for an open file \(identified by the file handle\). Its) s
+5 635 M
+( format is as follows:) s
+5 613 M
+( uint32 id) s
+5 602 M
+( string handle) s
+5 580 M
+( where `id' is the request identifier and `handle' is a file handle) s
+5 569 M
+( returned by SSH_FXP_OPEN. The server responds to this request with) s
+5 558 M
+( SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
+5 536 M
+(6.9 Setting File Attributes) s
+5 514 M
+( File attributes may be modified using the SSH_FXP_SETSTAT and) s
+5 503 M
+( SSH_FXP_FSETSTAT requests. These requests are used for operations) s
+5 492 M
+( such as changing the ownership, permissions or access times, as well) s
+5 481 M
+( as for truncating a file.) s
+5 459 M
+( The SSH_FXP_SETSTAT request is of the following format:) s
+5 437 M
+( uint32 id) s
+5 426 M
+( string path) s
+5 415 M
+( ATTRS attrs) s
+5 393 M
+( where `id' is the request identifier, `path' specifies the file) s
+5 382 M
+( system object \(e.g. file or directory\) whose attributes are to be) s
+5 371 M
+( modified, and `attrs' specifies the modifications to be made to its) s
+5 360 M
+( attributes. Attributes are discussed in more detail in Section) s
+5 349 M
+( ``File Attributes''.) s
+5 327 M
+( An error will be returned if the specified file system object does) s
+5 316 M
+( not exist or the user does not have sufficient rights to modify the) s
+5 305 M
+( specified attributes. The server responds to this request with a) s
+5 294 M
+( SSH_FXP_STATUS message.) s
+5 272 M
+( The SSH_FXP_FSETSTAT request modifies the attributes of a file which) s
+5 261 M
+( is already open. It has the following format:) s
+5 239 M
+( uint32 id) s
+5 228 M
+( string handle) s
+5 217 M
+( ATTRS attrs) s
+5 195 M
+( where `id' is the request identifier, `handle' \(MUST be returned by) s
+5 184 M
+( SSH_FXP_OPEN\) identifies the file whose attributes are to be) s
+5 173 M
+( modified, and `attrs' specifies the modifications to be made to its) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 17]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 18 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( attributes. Attributes are discussed in more detail in Section) s
+5 679 M
+( ``File Attributes''. The server will respond to this request with) s
+5 668 M
+( SSH_FXP_STATUS.) s
+5 646 M
+(6.10 Dealing with Symbolic links) s
+5 624 M
+( The SSH_FXP_READLINK request may be used to read the target of a) s
+5 613 M
+( symbolic link. It would have a data part as follows:) s
+5 591 M
+( uint32 id) s
+5 580 M
+( string path) s
+5 558 M
+( where `id' is the request identifier and `path' specifies the path) s
+5 547 M
+( name of the symlink to be read.) s
+5 525 M
+( The server will respond with a SSH_FXP_NAME packet containing only) s
+5 514 M
+( one name and a dummy attributes value. The name in the returned) s
+5 503 M
+( packet contains the target of the link. If an error occurs, the) s
+5 492 M
+( server may respond with SSH_FXP_STATUS.) s
+5 470 M
+( The SSH_FXP_SYMLINK request will create a symbolic link on the) s
+5 459 M
+( server. It is of the following format) s
+5 437 M
+( uint32 id) s
+5 426 M
+( string linkpath) s
+5 415 M
+( string targetpath) s
+5 393 M
+( where `id' is the request identifier, `linkpath' specifies the path) s
+5 382 M
+( name of the symlink to be created and `targetpath' specifies the) s
+5 371 M
+( target of the symlink. The server shall respond with a) s
+5 360 M
+( SSH_FXP_STATUS indicating either success \(SSH_FX_OK\) or an error) s
+5 349 M
+( condition.) s
+5 327 M
+(6.11 Canonicalizing the Server-Side Path Name) s
+5 305 M
+( The SSH_FXP_REALPATH request can be used to have the server) s
+5 294 M
+( canonicalize any given path name to an absolute path. This is useful) s
+5 283 M
+( for converting path names containing ".." components or relative) s
+5 272 M
+( pathnames without a leading slash into absolute paths. The format of) s
+5 261 M
+( the request is as follows:) s
+5 239 M
+( uint32 id) s
+5 228 M
+( string path) s
+5 206 M
+( where `id' is the request identifier and `path' specifies the path) s
+5 195 M
+( name to be canonicalized. The server will respond with a) s
+5 184 M
+( SSH_FXP_NAME packet containing only one name and a dummy attributes) s
+5 173 M
+( value. The name is the returned packet will be in canonical form.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 18]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (18,19) 10
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 19 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( If an error occurs, the server may also respond with SSH_FXP_STATUS.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 19]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 20 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(7. Responses from the Server to the Client) s
+5 668 M
+( The server responds to the client using one of a few response) s
+5 657 M
+( packets. All requests can return a SSH_FXP_STATUS response upon) s
+5 646 M
+( failure. When the operation is successful, any of the responses may) s
+5 635 M
+( be returned \(depending on the operation\). If no data needs to be) s
+5 624 M
+( returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK) s
+5 613 M
+( status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used) s
+5 602 M
+( to return a file handle \(for SSH_FXP_OPEN and SSH_FXP_OPENDIR) s
+5 591 M
+( requests\), SSH_FXP_DATA is used to return data from SSH_FXP_READ,) s
+5 580 M
+( SSH_FXP_NAME is used to return one or more file names from a) s
+5 569 M
+( SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is) s
+5 558 M
+( used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and) s
+5 547 M
+( SSH_FXP_FSTAT requests.) s
+5 525 M
+( Exactly one response will be returned for each request. Each) s
+5 514 M
+( response packet contains a request identifier which can be used to) s
+5 503 M
+( match each response with the corresponding request. Note that it is) s
+5 492 M
+( legal to have several requests outstanding simultaneously, and the) s
+5 481 M
+( server is allowed to send responses to them in a different order from) s
+5 470 M
+( the order in which the requests were sent \(the result of their) s
+5 459 M
+( execution, however, is guaranteed to be as if they had been processed) s
+5 448 M
+( one at a time in the order in which the requests were sent\).) s
+5 426 M
+( Response packets are of the same general format as request packets.) s
+5 415 M
+( Each response packet begins with the request identifier.) s
+5 393 M
+( The format of the data portion of the SSH_FXP_STATUS response is as) s
+5 382 M
+( follows:) s
+5 360 M
+( uint32 id) s
+5 349 M
+( uint32 error/status code) s
+5 338 M
+( string error message \(ISO-10646 UTF-8 [RFC-2279]\)) s
+5 327 M
+( string language tag \(as defined in [RFC-1766]\)) s
+5 305 M
+( where `id' is the request identifier, and `error/status code') s
+5 294 M
+( indicates the result of the requested operation. The value SSH_FX_OK) s
+5 283 M
+( indicates success, and all other values indicate failure.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 20]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (20,21) 11
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 21 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( Currently, the following values are defined \(other values may be) s
+5 679 M
+( defined by future versions of this protocol\):) s
+5 657 M
+( #define SSH_FX_OK 0) s
+5 646 M
+( #define SSH_FX_EOF 1) s
+5 635 M
+( #define SSH_FX_NO_SUCH_FILE 2) s
+5 624 M
+( #define SSH_FX_PERMISSION_DENIED 3) s
+5 613 M
+( #define SSH_FX_FAILURE 4) s
+5 602 M
+( #define SSH_FX_BAD_MESSAGE 5) s
+5 591 M
+( #define SSH_FX_NO_CONNECTION 6) s
+5 580 M
+( #define SSH_FX_CONNECTION_LOST 7) s
+5 569 M
+( #define SSH_FX_OP_UNSUPPORTED 8) s
+5 547 M
+( SSH_FX_OK) s
+5 536 M
+( Indicates successful completion of the operation.) s
+5 514 M
+( SSH_FX_EOF) s
+5 503 M
+( indicates end-of-file condition; for SSH_FX_READ it means that no) s
+5 492 M
+( more data is available in the file, and for SSH_FX_READDIR it) s
+5 481 M
+( indicates that no more files are contained in the directory.) s
+5 459 M
+( SSH_FX_NO_SUCH_FILE) s
+5 448 M
+( is returned when a reference is made to a file which should exist) s
+5 437 M
+( but doesn't.) s
+5 415 M
+( SSH_FX_PERMISSION_DENIED) s
+5 404 M
+( is returned when the authenticated user does not have sufficient) s
+5 393 M
+( permissions to perform the operation.) s
+5 371 M
+( SSH_FX_FAILURE) s
+5 360 M
+( is a generic catch-all error message; it should be returned if an) s
+5 349 M
+( error occurs for which there is no more specific error code) s
+5 338 M
+( defined.) s
+5 316 M
+( SSH_FX_BAD_MESSAGE) s
+5 305 M
+( may be returned if a badly formatted packet or protocol) s
+5 294 M
+( incompatibility is detected.) s
+5 272 M
+( SSH_FX_NO_CONNECTION) s
+5 261 M
+( is a pseudo-error which indicates that the client has no) s
+5 250 M
+( connection to the server \(it can only be generated locally by the) s
+5 239 M
+( client, and MUST NOT be returned by servers\).) s
+5 217 M
+( SSH_FX_CONNECTION_LOST) s
+5 206 M
+( is a pseudo-error which indicates that the connection to the) s
+5 195 M
+( server has been lost \(it can only be generated locally by the) s
+5 184 M
+( client, and MUST NOT be returned by servers\).) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 21]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 22 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( SSH_FX_OP_UNSUPPORTED) s
+5 679 M
+( indicates that an attempt was made to perform an operation which) s
+5 668 M
+( is not supported for the server \(it may be generated locally by) s
+5 657 M
+( the client if e.g. the version number exchange indicates that a) s
+5 646 M
+( required feature is not supported by the server, or it may be) s
+5 635 M
+( returned by the server if the server does not implement an) s
+5 624 M
+( operation\).) s
+5 602 M
+( The SSH_FXP_HANDLE response has the following format:) s
+5 580 M
+( uint32 id) s
+5 569 M
+( string handle) s
+5 547 M
+( where `id' is the request identifier, and `handle' is an arbitrary) s
+5 536 M
+( string that identifies an open file or directory on the server. The) s
+5 525 M
+( handle is opaque to the client; the client MUST NOT attempt to) s
+5 514 M
+( interpret or modify it in any way. The length of the handle string) s
+5 503 M
+( MUST NOT exceed 256 data bytes.) s
+5 481 M
+( The SSH_FXP_DATA response has the following format:) s
+5 459 M
+( uint32 id) s
+5 448 M
+( string data) s
+5 426 M
+( where `id' is the request identifier, and `data' is an arbitrary byte) s
+5 415 M
+( string containing the requested data. The data string may be at most) s
+5 404 M
+( the number of bytes requested in a SSH_FXP_READ request, but may also) s
+5 393 M
+( be shorter if end of file is reached or if the read is from something) s
+5 382 M
+( other than a regular file.) s
+5 360 M
+( The SSH_FXP_NAME response has the following format:) s
+5 338 M
+( uint32 id) s
+5 327 M
+( uint32 count) s
+5 316 M
+( repeats count times:) s
+5 305 M
+( string filename) s
+5 294 M
+( string longname) s
+5 283 M
+( ATTRS attrs) s
+5 261 M
+( where `id' is the request identifier, `count' is the number of names) s
+5 250 M
+( returned in this response, and the remaining fields repeat `count') s
+5 239 M
+( times \(so that all three fields are first included for the first) s
+5 228 M
+( file, then for the second file, etc\). In the repeated part,) s
+5 217 M
+( `filename' is a file name being returned \(for SSH_FXP_READDIR, it) s
+5 206 M
+( will be a relative name within the directory, without any path) s
+5 195 M
+( components; for SSH_FXP_REALPATH it will be an absolute path name\),) s
+5 184 M
+( `longname' is an expanded format for the file name, similar to what) s
+5 173 M
+( is returned by "ls -l" on Unix systems, and `attrs' is the attributes) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 22]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (22,23) 12
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 23 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+( of the file as described in Section ``File Attributes''.) s
+5 668 M
+( The format of the `longname' field is unspecified by this protocol.) s
+5 657 M
+( It MUST be suitable for use in the output of a directory listing) s
+5 646 M
+( command \(in fact, the recommended operation for a directory listing) s
+5 635 M
+( command is to simply display this data\). However, clients SHOULD NOT) s
+5 624 M
+( attempt to parse the longname field for file attributes; they SHOULD) s
+5 613 M
+( use the attrs field instead.) s
+5 591 M
+( The recommended format for the longname field is as follows:) s
+5 569 M
+( -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer) s
+5 558 M
+( 1234567890 123 12345678 12345678 12345678 123456789012) s
+5 536 M
+( Here, the first line is sample output, and the second field indicates) s
+5 525 M
+( widths of the various fields. Fields are separated by spaces. The) s
+5 514 M
+( first field lists file permissions for user, group, and others; the) s
+5 503 M
+( second field is link count; the third field is the name of the user) s
+5 492 M
+( who owns the file; the fourth field is the name of the group that) s
+5 481 M
+( owns the file; the fifth field is the size of the file in bytes; the) s
+5 470 M
+( sixth field \(which actually may contain spaces, but is fixed to 12) s
+5 459 M
+( characters\) is the file modification time, and the seventh field is) s
+5 448 M
+( the file name. Each field is specified to be a minimum of certain) s
+5 437 M
+( number of character positions \(indicated by the second line above\),) s
+5 426 M
+( but may also be longer if the data does not fit in the specified) s
+5 415 M
+( length.) s
+5 393 M
+( The SSH_FXP_ATTRS response has the following format:) s
+5 371 M
+( uint32 id) s
+5 360 M
+( ATTRS attrs) s
+5 338 M
+( where `id' is the request identifier, and `attrs' is the returned) s
+5 327 M
+( file attributes as described in Section ``File Attributes''.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 23]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 24 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(8. Vendor-Specific Extensions) s
+5 668 M
+( The SSH_FXP_EXTENDED request provides a generic extension mechanism) s
+5 657 M
+( for adding vendor-specific commands. The request has the following) s
+5 646 M
+( format:) s
+5 624 M
+( uint32 id) s
+5 613 M
+( string extended-request) s
+5 602 M
+( ... any request-specific data ...) s
+5 580 M
+( where `id' is the request identifier, and `extended-request' is a) s
+5 569 M
+( string of the format "name@domain", where domain is an internet) s
+5 558 M
+( domain name of the vendor defining the request. The rest of the) s
+5 547 M
+( request is completely vendor-specific, and servers should only) s
+5 536 M
+( attempt to interpret it if they recognize the `extended-request') s
+5 525 M
+( name.) s
+5 503 M
+( The server may respond to such requests using any of the response) s
+5 492 M
+( packets defined in Section ``Responses from the Server to the) s
+5 481 M
+( Client''. Additionally, the server may also respond with a) s
+5 470 M
+( SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does) s
+5 459 M
+( not recognize the `extended-request' name, then the server MUST) s
+5 448 M
+( respond with SSH_FXP_STATUS with error/status set to) s
+5 437 M
+( SSH_FX_OP_UNSUPPORTED.) s
+5 415 M
+( The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary) s
+5 404 M
+( extension-specific data from the server to the client. It is of the) s
+5 393 M
+( following format:) s
+5 371 M
+( uint32 id) s
+5 360 M
+( ... any request-specific data ...) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 24]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (24,25) 13
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 25 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(9. Security Considerations) s
+5 668 M
+( This protocol assumes that it is run over a secure channel and that) s
+5 657 M
+( the endpoints of the channel have been authenticated. Thus, this) s
+5 646 M
+( protocol assumes that it is externally protected from network-level) s
+5 635 M
+( attacks.) s
+5 613 M
+( This protocol provides file system access to arbitrary files on the) s
+5 602 M
+( server \(only constrained by the server implementation\). It is the) s
+5 591 M
+( responsibility of the server implementation to enforce any access) s
+5 580 M
+( controls that may be required to limit the access allowed for any) s
+5 569 M
+( particular user \(the user being authenticated externally to this) s
+5 558 M
+( protocol, typically using the SSH User Authentication Protocol [6].) s
+5 536 M
+( Care must be taken in the server implementation to check the validity) s
+5 525 M
+( of received file handle strings. The server should not rely on them) s
+5 514 M
+( directly; it MUST check the validity of each handle before relying on) s
+5 503 M
+( it.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 25]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 26 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(10. Changes from previous protocol versions) s
+5 668 M
+( The SSH File Transfer Protocol has changed over time, before it's) s
+5 657 M
+( standardization. The following is a description of the incompatible) s
+5 646 M
+( changes between different versions.) s
+5 624 M
+(10.1 Changes between versions 3 and 2) s
+5 602 M
+( o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.) s
+5 580 M
+( o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were) s
+5 569 M
+( added.) s
+5 547 M
+( o The SSH_FXP_STATUS message was changed to include fields `error) s
+5 536 M
+( message' and `language tag'.) s
+5 503 M
+(10.2 Changes between versions 2 and 1) s
+5 481 M
+( o The SSH_FXP_RENAME message was added.) s
+5 448 M
+(10.3 Changes between versions 1 and 0) s
+5 426 M
+( o Implementation changes, no actual protocol changes.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 26]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (26,27) 14
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 27 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(11. Trademark Issues) s
+5 668 M
+( "ssh" is a registered trademark of SSH Communications Security Corp) s
+5 657 M
+( in the United States and/or other countries.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 27]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 28 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(References) s
+5 668 M
+( [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and) s
+5 657 M
+( P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January) s
+5 646 M
+( 1999.) s
+5 624 M
+( [2] Institute of Electrical and Electronics Engineers, "Information) s
+5 613 M
+( Technology - Portable Operating System Interface \(POSIX\) - Part) s
+5 602 M
+( 1: System Application Program Interface \(API\) [C Language]",) s
+5 591 M
+( IEEE Standard 1003.2, 1996.) s
+5 569 M
+( [3] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 558 M
+( Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-) s
+5 547 M
+( architecture-09 \(work in progress\), July 2001.) s
+5 525 M
+( [4] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 514 M
+( Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-) s
+5 503 M
+( architecture-09 \(work in progress\), July 2001.) s
+5 481 M
+( [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 470 M
+( Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-11) s
+5 459 M
+( \(work in progress\), July 2001.) s
+5 437 M
+( [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 426 M
+( Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-) s
+5 415 M
+( userauth-11 \(work in progress\), July 2001.) s
+5 382 M
+(Authors' Addresses) s
+5 360 M
+( Tatu Ylonen) s
+5 349 M
+( SSH Communications Security Corp) s
+5 338 M
+( Fredrikinkatu 42) s
+5 327 M
+( HELSINKI FIN-00100) s
+5 316 M
+( Finland) s
+5 294 M
+( EMail: [email protected]) s
+5 261 M
+( Sami Lehtinen) s
+5 250 M
+( SSH Communications Security Corp) s
+5 239 M
+( Fredrikinkatu 42) s
+5 228 M
+( HELSINKI FIN-00100) s
+5 217 M
+( Finland) s
+5 195 M
+( EMail: [email protected]) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 28]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (28,29) 15
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 29 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2001) s
+5 690 M
+(Full Copyright Statement) s
+5 668 M
+( Copyright \(C\) The Internet Society \(2001\). All Rights Reserved.) s
+5 646 M
+( This document and translations of it may be copied and furnished to) s
+5 635 M
+( others, and derivative works that comment on or otherwise explain it) s
+5 624 M
+( or assist in its implementation may be prepared, copied, published) s
+5 613 M
+( and distributed, in whole or in part, without restriction of any) s
+5 602 M
+( kind, provided that the above copyright notice and this paragraph are) s
+5 591 M
+( included on all such copies and derivative works. However, this) s
+5 580 M
+( document itself may not be modified in any way, such as by removing) s
+5 569 M
+( the copyright notice or references to the Internet Society or other) s
+5 558 M
+( Internet organizations, except as needed for the purpose of) s
+5 547 M
+( developing Internet standards in which case the procedures for) s
+5 536 M
+( copyrights defined in the Internet Standards process must be) s
+5 525 M
+( followed, or as required to translate it into languages other than) s
+5 514 M
+( English.) s
+5 492 M
+( The limited permissions granted above are perpetual and will not be) s
+5 481 M
+( revoked by the Internet Society or its successors or assigns.) s
+5 459 M
+( This document and the information contained herein is provided on an) s
+5 448 M
+( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
+5 437 M
+( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
+5 426 M
+( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
+5 415 M
+( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
+5 404 M
+( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
+5 382 M
+(Acknowledgement) s
+5 360 M
+( Funding for the RFC Editor function is currently provided by the) s
+5 349 M
+( Internet Society.) s
+5 129 M
+(Ylonen & Lehtinen Expires April 1, 2002 [Page 29]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 30 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+_R
+S
+PStoPSsaved restore
+%%Trailer
+%%Pages: 30
+%%DocumentNeededResources: font Courier-Bold Courier
+%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt
new file mode 100644
index 0000000000..c4ec8c1125
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-02.txt
@@ -0,0 +1,1627 @@
+
+
+
+Network Working Group T. Ylonen
+Internet-Draft S. Lehtinen
+Expires: April 1, 2002 SSH Communications Security Corp
+ October 2001
+
+
+ SSH File Transfer Protocol
+ draft-ietf-secsh-filexfer-02.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on April 1, 2002.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ The SSH File Transfer Protocol provides secure file transfer
+ functionality over any reliable data stream. It is the standard file
+ transfer protocol for use with the SSH2 protocol. This document
+ describes the file transfer protocol and its interface to the SSH2
+ protocol suite.
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 1]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Use with the SSH Connection Protocol . . . . . . . . . . . . 4
+ 3. General Packet Format . . . . . . . . . . . . . . . . . . . 5
+ 4. Protocol Initialization . . . . . . . . . . . . . . . . . . 7
+ 5. File Attributes . . . . . . . . . . . . . . . . . . . . . . 8
+ 6. Requests From the Client to the Server . . . . . . . . . . . 10
+ 6.1 Request Synchronization and Reordering . . . . . . . . . . . 10
+ 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . . 11
+ 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . . 13
+ 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . . 14
+ 6.6 Creating and Deleting Directories . . . . . . . . . . . . . 15
+ 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . . 15
+ 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . . 16
+ 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . . 17
+ 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . . 18
+ 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . . 18
+ 7. Responses from the Server to the Client . . . . . . . . . . 20
+ 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . . 24
+ 9. Security Considerations . . . . . . . . . . . . . . . . . . 25
+ 10. Changes from previous protocol versions . . . . . . . . . . 26
+ 10.1 Changes between versions 3 and 2 . . . . . . . . . . . . . . 26
+ 10.2 Changes between versions 2 and 1 . . . . . . . . . . . . . . 26
+ 10.3 Changes between versions 1 and 0 . . . . . . . . . . . . . . 26
+ 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . . 27
+ References . . . . . . . . . . . . . . . . . . . . . . . . . 28
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 28
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . 29
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 2]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+1. Introduction
+
+ This protocol provides secure file transfer (and more generally file
+ system access) functionality over a reliable data stream, such as a
+ channel in the SSH2 protocol [3].
+
+ This protocol is designed so that it could be used to implement a
+ secure remote file system service, as well as a secure file transfer
+ service.
+
+ This protocol assumes that it runs over a secure channel, and that
+ the server has already authenticated the user at the client end, and
+ that the identity of the client user is externally available to the
+ server implementation.
+
+ In general, this protocol follows a simple request-response model.
+ Each request and response contains a sequence number and multiple
+ requests may be pending simultaneously. There are a relatively large
+ number of different request messages, but a small number of possible
+ response messages. Each request has one or more response messages
+ that may be returned in result (e.g., a read either returns data or
+ reports error status).
+
+ The packet format descriptions in this specification follow the
+ notation presented in the secsh architecture draft.[3].
+
+ Even though this protocol is described in the context of the SSH2
+ protocol, this protocol is general and independent of the rest of the
+ SSH2 protocol suite. It could be used in a number of different
+ applications, such as secure file transfer over TLS RFC 2246 [1] and
+ transfer of management information in VPN applications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 3]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+2. Use with the SSH Connection Protocol
+
+ When used with the SSH2 Protocol suite, this protocol is intended to
+ be used from the SSH Connection Protocol [5] as a subsystem, as
+ described in section ``Starting a Shell or a Command''. The
+ subsystem name used with this protocol is "sftp".
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 4]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+3. General Packet Format
+
+ All packets transmitted over the secure connection are of the
+ following format:
+
+ uint32 length
+ byte type
+ byte[length - 1] data payload
+
+ That is, they are just data preceded by 32-bit length and 8-bit type
+ fields. The `length' is the length of the data area, and does not
+ include the `length' field itself. The format and interpretation of
+ the data area depends on the packet type.
+
+ All packet descriptions below only specify the packet type and the
+ data that goes into the data field. Thus, they should be prefixed by
+ the `length' and `type' fields.
+
+ The maximum size of a packet is in practice determined by the client
+ (the maximum size of read or write requests that it sends, plus a few
+ bytes of packet overhead). All servers SHOULD support packets of at
+ least 34000 bytes (where the packet size refers to the full length,
+ including the header above). This should allow for reads and writes
+ of at most 32768 bytes.
+
+ There is no limit on the number of outstanding (non-acknowledged)
+ requests that the client may send to the server. In practice this is
+ limited by the buffering available on the data stream and the queuing
+ performed by the server. If the server's queues are full, it should
+ not read any more data from the stream, and flow control will prevent
+ the client from sending more requests. Note, however, that while
+ there is no restriction on the protocol level, the client's API may
+ provide a limit in order to prevent infinite queuing of outgoing
+ requests at the client.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 5]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ The following values are defined for packet types.
+
+ #define SSH_FXP_INIT 1
+ #define SSH_FXP_VERSION 2
+ #define SSH_FXP_OPEN 3
+ #define SSH_FXP_CLOSE 4
+ #define SSH_FXP_READ 5
+ #define SSH_FXP_WRITE 6
+ #define SSH_FXP_LSTAT 7
+ #define SSH_FXP_FSTAT 8
+ #define SSH_FXP_SETSTAT 9
+ #define SSH_FXP_FSETSTAT 10
+ #define SSH_FXP_OPENDIR 11
+ #define SSH_FXP_READDIR 12
+ #define SSH_FXP_REMOVE 13
+ #define SSH_FXP_MKDIR 14
+ #define SSH_FXP_RMDIR 15
+ #define SSH_FXP_REALPATH 16
+ #define SSH_FXP_STAT 17
+ #define SSH_FXP_RENAME 18
+ #define SSH_FXP_READLINK 19
+ #define SSH_FXP_SYMLINK 20
+ #define SSH_FXP_STATUS 101
+ #define SSH_FXP_HANDLE 102
+ #define SSH_FXP_DATA 103
+ #define SSH_FXP_NAME 104
+ #define SSH_FXP_ATTRS 105
+ #define SSH_FXP_EXTENDED 200
+ #define SSH_FXP_EXTENDED_REPLY 201
+
+ Additional packet types should only be defined if the protocol
+ version number (see Section ``Protocol Initialization'') is
+ incremented, and their use MUST be negotiated using the version
+ number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY
+ packets can be used to implement vendor-specific extensions. See
+ Section ``Vendor-Specific-Extensions'' for more details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 6]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+4. Protocol Initialization
+
+ When the file transfer protocol starts, it first sends a SSH_FXP_INIT
+ (including its version number) packet to the server. The server
+ responds with a SSH_FXP_VERSION packet, supplying the lowest of its
+ own and the client's version number. Both parties should from then
+ on adhere to particular version of the protocol.
+
+ The SSH_FXP_INIT packet (from client to server) has the following
+ data:
+
+ uint32 version
+ <extension data>
+
+ The SSH_FXP_VERSION packet (from server to client) has the following
+ data:
+
+ uint32 version
+ <extension data>
+
+ The version number of the protocol specified in this document is 3.
+ The version number should be incremented for each incompatible
+ revision of this protocol.
+
+ The extension data in the above packets may be empty, or may be a
+ sequence of
+
+ string extension_name
+ string extension_data
+
+ pairs (both strings MUST always be present if one is, but the
+ `extension_data' string may be of zero length). If present, these
+ strings indicate extensions to the baseline protocol. The
+ `extension_name' field(s) identify the name of the extension. The
+ name should be of the form "name@domain", where the domain is the DNS
+ domain name of the organization defining the extension. Additional
+ names that are not of this format may be defined later by the IETF.
+ Implementations MUST silently ignore any extensions whose name they
+ do not recognize.
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 7]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+5. File Attributes
+
+ A new compound data type is defined for encoding file attributes. It
+ is basically just a combination of elementary types, but is defined
+ once because of the non-trivial description of the fields and to
+ ensure maintainability.
+
+ The same encoding is used both when returning file attributes from
+ the server and when sending file attributes to the server. When
+ sending it to the server, the flags field specifies which attributes
+ are included, and the server will use default values for the
+ remaining attributes (or will not modify the values of remaining
+ attributes). When receiving attributes from the server, the flags
+ specify which attributes are included in the returned data. The
+ server normally returns all attributes it knows about.
+
+ uint32 flags
+ uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE
+ uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID
+ uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID
+ uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS
+ uint32 atime present only if flag SSH_FILEXFER_ACMODTIME
+ uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME
+ uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED
+ string extended_type
+ string extended_data
+ ... more extended data (extended_type - extended_data pairs),
+ so that number of pairs equals extended_count
+
+ The `flags' specify which of the fields are present. Those fields
+ for which the corresponding flag is not set are not present (not
+ included in the packet). New flags can only be added by incrementing
+ the protocol version number (or by using the extension mechanism
+ described below).
+
+ The `size' field specifies the size of the file in bytes.
+
+ The `uid' and `gid' fields contain numeric Unix-like user and group
+ identifiers, respectively.
+
+ The `permissions' field contains a bit mask of file permissions as
+ defined by posix [1].
+
+ The `atime' and `mtime' contain the access and modification times of
+ the files, respectively. They are represented as seconds from Jan 1,
+ 1970 in UTC.
+
+ The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 8]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ mechanism for vendor-specific extensions. If the flag is specified,
+ then the `extended_count' field is present. It specifies the number
+ of extended_type-extended_data pairs that follow. Each of these
+ pairs specifies an extended attribute. For each of the attributes,
+ the extended_type field should be a string of the format
+ "name@domain", where "domain" is a valid, registered domain name and
+ "name" identifies the method. The IETF may later standardize certain
+ names that deviate from this format (e.g., that do not contain the
+ "@" sign). The interpretation of `extended_data' depends on the
+ type. Implementations SHOULD ignore extended data fields that they
+ do not understand.
+
+ Additional fields can be added to the attributes by either defining
+ additional bits to the flags field to indicate their presence, or by
+ defining extended attributes for them. The extended attributes
+ mechanism is recommended for most purposes; additional flags bits
+ should only be defined by an IETF standards action that also
+ increments the protocol version number. The use of such new fields
+ MUST be negotiated by the version number in the protocol exchange.
+ It is a protocol error if a packet with unsupported protocol bits is
+ received.
+
+ The flags bits are defined to have the following values:
+
+ #define SSH_FILEXFER_ATTR_SIZE 0x00000001
+ #define SSH_FILEXFER_ATTR_UIDGID 0x00000002
+ #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
+ #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008
+ #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 9]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+6. Requests From the Client to the Server
+
+ Requests from the client to the server represent the various file
+ system operations. Each request begins with an `id' field, which is
+ a 32-bit identifier identifying the request (selected by the client).
+ The same identifier will be returned in the response to the request.
+ One possible implementation of it is a monotonically increasing
+ request sequence number (modulo 2^32).
+
+ Many operations in the protocol operate on open files. The
+ SSH_FXP_OPEN request can return a file handle (which is an opaque
+ variable-length string) which may be used to access the file later
+ (e.g. in a read operation). The client MUST NOT send requests the
+ server with bogus or closed handles. However, the server MUST
+ perform adequate checks on the handle in order to avoid security
+ risks due to fabricated handles.
+
+ This design allows either stateful and stateless server
+ implementation, as well as an implementation which caches state
+ between requests but may also flush it. The contents of the file
+ handle string are entirely up to the server and its design. The
+ client should not modify or attempt to interpret the file handle
+ strings.
+
+ The file handle strings MUST NOT be longer than 256 bytes.
+
+6.1 Request Synchronization and Reordering
+
+ The protocol and implementations MUST process requests relating to
+ the same file in the order in which they are received. In other
+ words, if an application submits multiple requests to the server, the
+ results in the responses will be the same as if it had sent the
+ requests one at a time and waited for the response in each case. For
+ example, the server may process non-overlapping read/write requests
+ to the same file in parallel, but overlapping reads and writes cannot
+ be reordered or parallelized. However, there are no ordering
+ restrictions on the server for processing requests from two different
+ file transfer connections. The server may interleave and parallelize
+ them at will.
+
+ There are no restrictions on the order in which responses to
+ outstanding requests are delivered to the client, except that the
+ server must ensure fairness in the sense that processing of no
+ request will be indefinitely delayed even if the client is sending
+ other requests so that there are multiple outstanding requests all
+ the time.
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 10]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+6.2 File Names
+
+ This protocol represents file names as strings. File names are
+ assumed to use the slash ('/') character as a directory separator.
+
+ File names starting with a slash are "absolute", and are relative to
+ the root of the file system. Names starting with any other character
+ are relative to the user's default directory (home directory). Note
+ that identifying the user is assumed to take place outside of this
+ protocol.
+
+ Servers SHOULD interpret a path name component ".." as referring to
+ the parent directory, and "." as referring to the current directory.
+ If the server implementation limits access to certain parts of the
+ file system, it must be extra careful in parsing file names when
+ enforcing such restrictions. There have been numerous reported
+ security bugs where a ".." in a path name has allowed access outside
+ the intended area.
+
+ An empty path name is valid, and it refers to the user's default
+ directory (usually the user's home directory).
+
+ Otherwise, no syntax is defined for file names by this specification.
+ Clients should not make any other assumptions; however, they can
+ splice path name components returned by SSH_FXP_READDIR together
+ using a slash ('/') as the separator, and that will work as expected.
+
+ It is understood that the lack of well-defined semantics for file
+ names may cause interoperability problems between clients and servers
+ using radically different operating systems. However, this approach
+ is known to work acceptably with most systems, and alternative
+ approaches that e.g. treat file names as sequences of structured
+ components are quite complicated.
+
+6.3 Opening, Creating, and Closing Files
+
+ Files are opened and created using the SSH_FXP_OPEN message, whose
+ data part is as follows:
+
+ uint32 id
+ string filename
+ uint32 pflags
+ ATTRS attrs
+
+ The `id' field is the request identifier as for all requests.
+
+ The `filename' field specifies the file name. See Section ``File
+ Names'' for more information.
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 11]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ The `pflags' field is a bitmask. The following bits have been
+ defined.
+
+ #define SSH_FXF_READ 0x00000001
+ #define SSH_FXF_WRITE 0x00000002
+ #define SSH_FXF_APPEND 0x00000004
+ #define SSH_FXF_CREAT 0x00000008
+ #define SSH_FXF_TRUNC 0x00000010
+ #define SSH_FXF_EXCL 0x00000020
+
+ These have the following meanings:
+
+ SSH_FXF_READ
+ Open the file for reading.
+
+ SSH_FXF_WRITE
+ Open the file for writing. If both this and SSH_FXF_READ are
+ specified, the file is opened for both reading and writing.
+
+ SSH_FXF_APPEND
+ Force all writes to append data at the end of the file.
+
+ SSH_FXF_CREAT
+ If this flag is specified, then a new file will be created if one
+ does not already exist (if O_TRUNC is specified, the new file will
+ be truncated to zero length if it previously exists).
+
+ SSH_FXF_TRUNC
+ Forces an existing file with the same name to be truncated to zero
+ length when creating a file by specifying SSH_FXF_CREAT.
+ SSH_FXF_CREAT MUST also be specified if this flag is used.
+
+ SSH_FXF_EXCL
+ Causes the request to fail if the named file already exists.
+ SSH_FXF_CREAT MUST also be specified if this flag is used.
+
+ The `attrs' field specifies the initial attributes for the file.
+ Default values will be used for those attributes that are not
+ specified. See Section ``File Attributes'' for more information.
+
+ Regardless the server operating system, the file will always be
+ opened in "binary" mode (i.e., no translations between different
+ character sets and newline encodings).
+
+ The response to this message will be either SSH_FXP_HANDLE (if the
+ operation is successful) or SSH_FXP_STATUS (if the operation fails).
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 12]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ A file is closed by using the SSH_FXP_CLOSE request. Its data field
+ has the following format:
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is a handle
+ previously returned in the response to SSH_FXP_OPEN or
+ SSH_FXP_OPENDIR. The handle becomes invalid immediately after this
+ request has been sent.
+
+ The response to this request will be a SSH_FXP_STATUS message. One
+ should note that on some server platforms even a close can fail.
+ This can happen e.g. if the server operating system caches writes,
+ and an error occurs while flushing cached writes during the close.
+
+6.4 Reading and Writing
+
+ Once a file has been opened, it can be read using the SSH_FXP_READ
+ message, which has the following format:
+
+ uint32 id
+ string handle
+ uint64 offset
+ uint32 len
+
+ where `id' is the request identifier, `handle' is an open file handle
+ returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative
+ to the beginning of the file from where to start reading, and `len'
+ is the maximum number of bytes to read.
+
+ In response to this request, the server will read as many bytes as it
+ can from the file (up to `len'), and return them in a SSH_FXP_DATA
+ message. If an error occurs or EOF is encountered before reading any
+ data, the server will respond with SSH_FXP_STATUS. For normal disk
+ files, it is guaranteed that this will read the specified number of
+ bytes, or up to end of file. For e.g. device files this may return
+ fewer bytes than requested.
+
+ Writing to a file is achieved using the SSH_FXP_WRITE message, which
+ has the following format:
+
+ uint32 id
+ string handle
+ uint64 offset
+ string data
+
+ where `id' is a request identifier, `handle' is a file handle
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 13]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the
+ beginning of the file where to start writing, and `data' is the data
+ to be written.
+
+ The write will extend the file if writing beyond the end of the file.
+ It is legal to write way beyond the end of the file; the semantics
+ are to write zeroes from the end of the file to the specified offset
+ and then the data. On most operating systems, such writes do not
+ allocate disk space but instead leave "holes" in the file.
+
+ The server responds to a write request with a SSH_FXP_STATUS message.
+
+6.5 Removing and Renaming Files
+
+ Files can be removed using the SSH_FXP_REMOVE message. It has the
+ following format:
+
+ uint32 id
+ string filename
+
+ where `id' is the request identifier and `filename' is the name of
+ the file to be removed. See Section ``File Names'' for more
+ information. This request cannot be used to remove directories.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+ message.
+
+ Files (and directories) can be renamed using the SSH_FXP_RENAME
+ message. Its data is as follows:
+
+ uint32 id
+ string oldpath
+ string newpath
+
+ where `id' is the request identifier, `oldpath' is the name of an
+ existing file or directory, and `newpath' is the new name for the
+ file or directory. It is an error if there already exists a file
+ with the name specified by newpath. The server may also fail rename
+ requests in other situations, for example if `oldpath' and `newpath'
+ point to different file systems on the server.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+ message.
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 14]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+6.6 Creating and Deleting Directories
+
+ New directories can be created using the SSH_FXP_MKDIR request. It
+ has the following format:
+
+ uint32 id
+ string path
+ ATTRS attrs
+
+ where `id' is the request identifier, `path' and `attrs' specifies
+ the modifications to be made to its attributes. See Section ``File
+ Names'' for more information on file names. Attributes are discussed
+ in more detail in Section ``File Attributes''. specifies the
+ directory to be created. An error will be returned if a file or
+ directory with the specified path already exists. The server will
+ respond to this request with a SSH_FXP_STATUS message.
+
+ Directories can be removed using the SSH_FXP_RMDIR request, which
+ has the following format:
+
+ uint32 id
+ string path
+
+ where `id' is the request identifier, and `path' specifies the
+ directory to be removed. See Section ``File Names'' for more
+ information on file names. An error will be returned if no directory
+ with the specified path exists, or if the specified directory is not
+ empty, or if the path specified a file system object other than a
+ directory. The server responds to this request with a SSH_FXP_STATUS
+ message.
+
+6.7 Scanning Directories
+
+ The files in a directory can be listed using the SSH_FXP_OPENDIR and
+ SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one
+ or more file names with full file attributes for each file. The
+ client should call SSH_FXP_READDIR repeatedly until it has found the
+ file it is looking for or until the server responds with a
+ SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if
+ there are no more files in the directory). The client should then
+ close the handle using the SSH_FXP_CLOSE request.
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 15]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ The SSH_FXP_OPENDIR opens a directory for reading. It has the
+ following format:
+
+ uint32 id
+ string path
+
+ where `id' is the request identifier and `path' is the path name of
+ the directory to be listed (without any trailing slash). See Section
+ ``File Names'' for more information on file names. This will return
+ an error if the path does not specify a directory or if the directory
+ is not readable. The server will respond to this request with either
+ a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.
+
+ Once the directory has been successfully opened, files (and
+ directories) contained in it can be listed using SSH_FXP_READDIR
+ requests. These are of the format
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is a handle
+ returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to
+ use an ordinary file handle returned by SSH_FXP_OPEN.)
+
+ The server responds to this request with either a SSH_FXP_NAME or a
+ SSH_FXP_STATUS message. One or more names may be returned at a time.
+ Full status information is returned for each name in order to speed
+ up typical directory listings.
+
+ When the client no longer wishes to read more names from the
+ directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle
+ should be closed regardless of whether an error has occurred or not.
+
+6.8 Retrieving File Attributes
+
+ Very often, file attributes are automatically returned by
+ SSH_FXP_READDIR. However, sometimes there is need to specifically
+ retrieve the attributes for a named file. This can be done using the
+ SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.
+
+ SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT
+ follows symbolic links on the server, whereas SSH_FXP_LSTAT does not
+ follow symbolic links. Both have the same format:
+
+ uint32 id
+ string path
+
+ where `id' is the request identifier, and `path' specifies the file
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 16]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ system object for which status is to be returned. The server
+ responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.
+
+ SSH_FXP_FSTAT differs from the others in that it returns status
+ information for an open file (identified by the file handle). Its
+ format is as follows:
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier and `handle' is a file handle
+ returned by SSH_FXP_OPEN. The server responds to this request with
+ SSH_FXP_ATTRS or SSH_FXP_STATUS.
+
+6.9 Setting File Attributes
+
+ File attributes may be modified using the SSH_FXP_SETSTAT and
+ SSH_FXP_FSETSTAT requests. These requests are used for operations
+ such as changing the ownership, permissions or access times, as well
+ as for truncating a file.
+
+ The SSH_FXP_SETSTAT request is of the following format:
+
+ uint32 id
+ string path
+ ATTRS attrs
+
+ where `id' is the request identifier, `path' specifies the file
+ system object (e.g. file or directory) whose attributes are to be
+ modified, and `attrs' specifies the modifications to be made to its
+ attributes. Attributes are discussed in more detail in Section
+ ``File Attributes''.
+
+ An error will be returned if the specified file system object does
+ not exist or the user does not have sufficient rights to modify the
+ specified attributes. The server responds to this request with a
+ SSH_FXP_STATUS message.
+
+ The SSH_FXP_FSETSTAT request modifies the attributes of a file which
+ is already open. It has the following format:
+
+ uint32 id
+ string handle
+ ATTRS attrs
+
+ where `id' is the request identifier, `handle' (MUST be returned by
+ SSH_FXP_OPEN) identifies the file whose attributes are to be
+ modified, and `attrs' specifies the modifications to be made to its
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 17]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ attributes. Attributes are discussed in more detail in Section
+ ``File Attributes''. The server will respond to this request with
+ SSH_FXP_STATUS.
+
+6.10 Dealing with Symbolic links
+
+ The SSH_FXP_READLINK request may be used to read the target of a
+ symbolic link. It would have a data part as follows:
+
+ uint32 id
+ string path
+
+ where `id' is the request identifier and `path' specifies the path
+ name of the symlink to be read.
+
+ The server will respond with a SSH_FXP_NAME packet containing only
+ one name and a dummy attributes value. The name in the returned
+ packet contains the target of the link. If an error occurs, the
+ server may respond with SSH_FXP_STATUS.
+
+ The SSH_FXP_SYMLINK request will create a symbolic link on the
+ server. It is of the following format
+
+ uint32 id
+ string linkpath
+ string targetpath
+
+ where `id' is the request identifier, `linkpath' specifies the path
+ name of the symlink to be created and `targetpath' specifies the
+ target of the symlink. The server shall respond with a
+ SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error
+ condition.
+
+6.11 Canonicalizing the Server-Side Path Name
+
+ The SSH_FXP_REALPATH request can be used to have the server
+ canonicalize any given path name to an absolute path. This is useful
+ for converting path names containing ".." components or relative
+ pathnames without a leading slash into absolute paths. The format of
+ the request is as follows:
+
+ uint32 id
+ string path
+
+ where `id' is the request identifier and `path' specifies the path
+ name to be canonicalized. The server will respond with a
+ SSH_FXP_NAME packet containing only one name and a dummy attributes
+ value. The name is the returned packet will be in canonical form.
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 18]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ If an error occurs, the server may also respond with SSH_FXP_STATUS.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 19]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+7. Responses from the Server to the Client
+
+ The server responds to the client using one of a few response
+ packets. All requests can return a SSH_FXP_STATUS response upon
+ failure. When the operation is successful, any of the responses may
+ be returned (depending on the operation). If no data needs to be
+ returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK
+ status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used
+ to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR
+ requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ,
+ SSH_FXP_NAME is used to return one or more file names from a
+ SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is
+ used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and
+ SSH_FXP_FSTAT requests.
+
+ Exactly one response will be returned for each request. Each
+ response packet contains a request identifier which can be used to
+ match each response with the corresponding request. Note that it is
+ legal to have several requests outstanding simultaneously, and the
+ server is allowed to send responses to them in a different order from
+ the order in which the requests were sent (the result of their
+ execution, however, is guaranteed to be as if they had been processed
+ one at a time in the order in which the requests were sent).
+
+ Response packets are of the same general format as request packets.
+ Each response packet begins with the request identifier.
+
+ The format of the data portion of the SSH_FXP_STATUS response is as
+ follows:
+
+ uint32 id
+ uint32 error/status code
+ string error message (ISO-10646 UTF-8 [RFC-2279])
+ string language tag (as defined in [RFC-1766])
+
+ where `id' is the request identifier, and `error/status code'
+ indicates the result of the requested operation. The value SSH_FX_OK
+ indicates success, and all other values indicate failure.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 20]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ Currently, the following values are defined (other values may be
+ defined by future versions of this protocol):
+
+ #define SSH_FX_OK 0
+ #define SSH_FX_EOF 1
+ #define SSH_FX_NO_SUCH_FILE 2
+ #define SSH_FX_PERMISSION_DENIED 3
+ #define SSH_FX_FAILURE 4
+ #define SSH_FX_BAD_MESSAGE 5
+ #define SSH_FX_NO_CONNECTION 6
+ #define SSH_FX_CONNECTION_LOST 7
+ #define SSH_FX_OP_UNSUPPORTED 8
+
+ SSH_FX_OK
+ Indicates successful completion of the operation.
+
+ SSH_FX_EOF
+ indicates end-of-file condition; for SSH_FX_READ it means that no
+ more data is available in the file, and for SSH_FX_READDIR it
+ indicates that no more files are contained in the directory.
+
+ SSH_FX_NO_SUCH_FILE
+ is returned when a reference is made to a file which should exist
+ but doesn't.
+
+ SSH_FX_PERMISSION_DENIED
+ is returned when the authenticated user does not have sufficient
+ permissions to perform the operation.
+
+ SSH_FX_FAILURE
+ is a generic catch-all error message; it should be returned if an
+ error occurs for which there is no more specific error code
+ defined.
+
+ SSH_FX_BAD_MESSAGE
+ may be returned if a badly formatted packet or protocol
+ incompatibility is detected.
+
+ SSH_FX_NO_CONNECTION
+ is a pseudo-error which indicates that the client has no
+ connection to the server (it can only be generated locally by the
+ client, and MUST NOT be returned by servers).
+
+ SSH_FX_CONNECTION_LOST
+ is a pseudo-error which indicates that the connection to the
+ server has been lost (it can only be generated locally by the
+ client, and MUST NOT be returned by servers).
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 21]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ SSH_FX_OP_UNSUPPORTED
+ indicates that an attempt was made to perform an operation which
+ is not supported for the server (it may be generated locally by
+ the client if e.g. the version number exchange indicates that a
+ required feature is not supported by the server, or it may be
+ returned by the server if the server does not implement an
+ operation).
+
+ The SSH_FXP_HANDLE response has the following format:
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is an arbitrary
+ string that identifies an open file or directory on the server. The
+ handle is opaque to the client; the client MUST NOT attempt to
+ interpret or modify it in any way. The length of the handle string
+ MUST NOT exceed 256 data bytes.
+
+ The SSH_FXP_DATA response has the following format:
+
+ uint32 id
+ string data
+
+ where `id' is the request identifier, and `data' is an arbitrary byte
+ string containing the requested data. The data string may be at most
+ the number of bytes requested in a SSH_FXP_READ request, but may also
+ be shorter if end of file is reached or if the read is from something
+ other than a regular file.
+
+ The SSH_FXP_NAME response has the following format:
+
+ uint32 id
+ uint32 count
+ repeats count times:
+ string filename
+ string longname
+ ATTRS attrs
+
+ where `id' is the request identifier, `count' is the number of names
+ returned in this response, and the remaining fields repeat `count'
+ times (so that all three fields are first included for the first
+ file, then for the second file, etc). In the repeated part,
+ `filename' is a file name being returned (for SSH_FXP_READDIR, it
+ will be a relative name within the directory, without any path
+ components; for SSH_FXP_REALPATH it will be an absolute path name),
+ `longname' is an expanded format for the file name, similar to what
+ is returned by "ls -l" on Unix systems, and `attrs' is the attributes
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 22]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+ of the file as described in Section ``File Attributes''.
+
+ The format of the `longname' field is unspecified by this protocol.
+ It MUST be suitable for use in the output of a directory listing
+ command (in fact, the recommended operation for a directory listing
+ command is to simply display this data). However, clients SHOULD NOT
+ attempt to parse the longname field for file attributes; they SHOULD
+ use the attrs field instead.
+
+ The recommended format for the longname field is as follows:
+
+ -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer
+ 1234567890 123 12345678 12345678 12345678 123456789012
+
+ Here, the first line is sample output, and the second field indicates
+ widths of the various fields. Fields are separated by spaces. The
+ first field lists file permissions for user, group, and others; the
+ second field is link count; the third field is the name of the user
+ who owns the file; the fourth field is the name of the group that
+ owns the file; the fifth field is the size of the file in bytes; the
+ sixth field (which actually may contain spaces, but is fixed to 12
+ characters) is the file modification time, and the seventh field is
+ the file name. Each field is specified to be a minimum of certain
+ number of character positions (indicated by the second line above),
+ but may also be longer if the data does not fit in the specified
+ length.
+
+ The SSH_FXP_ATTRS response has the following format:
+
+ uint32 id
+ ATTRS attrs
+
+ where `id' is the request identifier, and `attrs' is the returned
+ file attributes as described in Section ``File Attributes''.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 23]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+8. Vendor-Specific Extensions
+
+ The SSH_FXP_EXTENDED request provides a generic extension mechanism
+ for adding vendor-specific commands. The request has the following
+ format:
+
+ uint32 id
+ string extended-request
+ ... any request-specific data ...
+
+ where `id' is the request identifier, and `extended-request' is a
+ string of the format "name@domain", where domain is an internet
+ domain name of the vendor defining the request. The rest of the
+ request is completely vendor-specific, and servers should only
+ attempt to interpret it if they recognize the `extended-request'
+ name.
+
+ The server may respond to such requests using any of the response
+ packets defined in Section ``Responses from the Server to the
+ Client''. Additionally, the server may also respond with a
+ SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does
+ not recognize the `extended-request' name, then the server MUST
+ respond with SSH_FXP_STATUS with error/status set to
+ SSH_FX_OP_UNSUPPORTED.
+
+ The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary
+ extension-specific data from the server to the client. It is of the
+ following format:
+
+ uint32 id
+ ... any request-specific data ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 24]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+9. Security Considerations
+
+ This protocol assumes that it is run over a secure channel and that
+ the endpoints of the channel have been authenticated. Thus, this
+ protocol assumes that it is externally protected from network-level
+ attacks.
+
+ This protocol provides file system access to arbitrary files on the
+ server (only constrained by the server implementation). It is the
+ responsibility of the server implementation to enforce any access
+ controls that may be required to limit the access allowed for any
+ particular user (the user being authenticated externally to this
+ protocol, typically using the SSH User Authentication Protocol [6].
+
+ Care must be taken in the server implementation to check the validity
+ of received file handle strings. The server should not rely on them
+ directly; it MUST check the validity of each handle before relying on
+ it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 25]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+10. Changes from previous protocol versions
+
+ The SSH File Transfer Protocol has changed over time, before it's
+ standardization. The following is a description of the incompatible
+ changes between different versions.
+
+10.1 Changes between versions 3 and 2
+
+ o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.
+
+ o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were
+ added.
+
+ o The SSH_FXP_STATUS message was changed to include fields `error
+ message' and `language tag'.
+
+
+10.2 Changes between versions 2 and 1
+
+ o The SSH_FXP_RENAME message was added.
+
+
+10.3 Changes between versions 1 and 0
+
+ o Implementation changes, no actual protocol changes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 26]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+11. Trademark Issues
+
+ "ssh" is a registered trademark of SSH Communications Security Corp
+ in the United States and/or other countries.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 27]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+References
+
+ [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and
+ P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January
+ 1999.
+
+ [2] Institute of Electrical and Electronics Engineers, "Information
+ Technology - Portable Operating System Interface (POSIX) - Part
+ 1: System Application Program Interface (API) [C Language]",
+ IEEE Standard 1003.2, 1996.
+
+ [3] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-
+ architecture-09 (work in progress), July 2001.
+
+ [4] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-
+ architecture-09 (work in progress), July 2001.
+
+ [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-11
+ (work in progress), July 2001.
+
+ [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-
+ userauth-11 (work in progress), July 2001.
+
+
+Authors' Addresses
+
+ Tatu Ylonen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+ Sami Lehtinen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 28]
+
+Internet-Draft SSH File Transfer Protocol October 2001
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Lehtinen Expires April 1, 2002 [Page 29]
+
+
+
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps
new file mode 100644
index 0000000000..6a40cd6067
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.2.ps
@@ -0,0 +1,3511 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 75 0 595 747
+%%Title: Enscript Output
+%%For: Magnus Thoang
+%%Creator: GNU enscript 1.6.1
+%%CreationDate: Wed Nov 12 12:18:50 2003
+%%Orientation: Portrait
+%%Pages: 18 0
+%%DocumentMedia: A4 595 842 0 () ()
+%%DocumentNeededResources: (atend)
+%%EndComments
+%%BeginProlog
+%%BeginProcSet: PStoPS 1 15
+userdict begin
+[/showpage/erasepage/copypage]{dup where{pop dup load
+ type/operatortype eq{1 array cvx dup 0 3 index cvx put
+ bind def}{pop}ifelse}{pop}ifelse}forall
+[/letter/legal/executivepage/a4/a4small/b5/com10envelope
+ /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
+ /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
+ {pop{}def}ifelse}{pop}ifelse}forall
+/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
+ {pop def}ifelse}{def}ifelse
+/PStoPSmatrix matrix currentmatrix def
+/PStoPSxform matrix def/PStoPSclip{clippath}def
+/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
+/initmatrix{matrix defaultmatrix setmatrix}bind def
+/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
+ [{currentpoint}stopped{$error/newerror false put{newpath}}
+ {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
+ {[/newpath cvx{/moveto cvx}{/lineto cvx}
+ {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
+ stopped{$error/errorname get/invalidaccess eq{cleartomark
+ $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
+ /initclip dup load dup type dup/operatortype eq{pop exch pop}
+ {dup/arraytype eq exch/packedarraytype eq or
+ {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
+ {pop cvx}ifelse}ifelse
+ {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
+/initgraphics{initmatrix newpath initclip 1 setlinewidth
+ 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
+ 10 setmiterlimit}bind def
+end
+%%EndProcSet
+%%BeginResource: procset Enscript-Prolog 1.6 1
+%
+% Procedures.
+%
+
+/_S { % save current state
+ /_s save def
+} def
+/_R { % restore from saved state
+ _s restore
+} def
+
+/S { % showpage protecting gstate
+ gsave
+ showpage
+ grestore
+} bind def
+
+/MF { % fontname newfontname -> - make a new encoded font
+ /newfontname exch def
+ /fontname exch def
+
+ /fontdict fontname findfont def
+ /newfont fontdict maxlength dict def
+
+ fontdict {
+ exch
+ dup /FID eq {
+ % skip FID pair
+ pop pop
+ } {
+ % copy to the new font dictionary
+ exch newfont 3 1 roll put
+ } ifelse
+ } forall
+
+ newfont /FontName newfontname put
+
+ % insert only valid encoding vectors
+ encoding_vector length 256 eq {
+ newfont /Encoding encoding_vector put
+ } if
+
+ newfontname newfont definefont pop
+} def
+
+/SF { % fontname width height -> - set a new font
+ /height exch def
+ /width exch def
+
+ findfont
+ [width 0 0 height 0 0] makefont setfont
+} def
+
+/SUF { % fontname width height -> - set a new user font
+ /height exch def
+ /width exch def
+
+ /F-gs-user-font MF
+ /F-gs-user-font width height SF
+} def
+
+/M {moveto} bind def
+/s {show} bind def
+
+/Box { % x y w h -> - define box path
+ /d_h exch def /d_w exch def /d_y exch def /d_x exch def
+ d_x d_y moveto
+ d_w 0 rlineto
+ 0 d_h rlineto
+ d_w neg 0 rlineto
+ closepath
+} def
+
+/bgs { % x y height blskip gray str -> - show string with bg color
+ /str exch def
+ /gray exch def
+ /blskip exch def
+ /height exch def
+ /y exch def
+ /x exch def
+
+ gsave
+ x y blskip sub str stringwidth pop height Box
+ gray setgray
+ fill
+ grestore
+ x y M str s
+} def
+
+% Highlight bars.
+/highlight_bars { % nlines lineheight output_y_margin gray -> -
+ gsave
+ setgray
+ /ymarg exch def
+ /lineheight exch def
+ /nlines exch def
+
+ % This 2 is just a magic number to sync highlight lines to text.
+ 0 d_header_y ymarg sub 2 sub translate
+
+ /cw d_output_w cols div def
+ /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
+
+ % for each column
+ 0 1 cols 1 sub {
+ cw mul /xp exch def
+
+ % for each rows
+ 0 1 nrows 1 sub {
+ /rn exch def
+ rn lineheight mul neg /yp exch def
+ rn nlines idiv 2 mod 0 eq {
+ % Draw highlight bar. 4 is just a magic indentation.
+ xp 4 add yp cw 8 sub lineheight neg Box fill
+ } if
+ } for
+ } for
+
+ grestore
+} def
+
+% Line highlight bar.
+/line_highlight { % x y width height gray -> -
+ gsave
+ /gray exch def
+ Box gray setgray fill
+ grestore
+} def
+
+% Column separator lines.
+/column_lines {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h translate
+ /cw d_output_w cols div def
+ 1 1 cols 1 sub {
+ cw mul 0 moveto
+ 0 d_output_h rlineto stroke
+ } for
+ grestore
+} def
+
+% Column borders.
+/column_borders {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h moveto
+ 0 d_output_h rlineto
+ d_output_w 0 rlineto
+ 0 d_output_h neg rlineto
+ closepath stroke
+ grestore
+} def
+
+% Do the actual underlay drawing
+/draw_underlay {
+ ul_style 0 eq {
+ ul_str true charpath stroke
+ } {
+ ul_str show
+ } ifelse
+} def
+
+% Underlay
+/underlay { % - -> -
+ gsave
+ 0 d_page_h translate
+ d_page_h neg d_page_w atan rotate
+
+ ul_gray setgray
+ ul_font setfont
+ /dw d_page_h dup mul d_page_w dup mul add sqrt def
+ ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
+ draw_underlay
+ grestore
+} def
+
+/user_underlay { % - -> -
+ gsave
+ ul_x ul_y translate
+ ul_angle rotate
+ ul_gray setgray
+ ul_font setfont
+ 0 0 ul_h_ptsize 2 div sub moveto
+ draw_underlay
+ grestore
+} def
+
+% Page prefeed
+/page_prefeed { % bool -> -
+ statusdict /prefeed known {
+ statusdict exch /prefeed exch put
+ } {
+ pop
+ } ifelse
+} def
+
+% Wrapped line markers
+/wrapped_line_mark { % x y charwith charheight type -> -
+ /type exch def
+ /h exch def
+ /w exch def
+ /y exch def
+ /x exch def
+
+ type 2 eq {
+ % Black boxes (like TeX does)
+ gsave
+ 0 setlinewidth
+ x w 4 div add y M
+ 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
+ closepath fill
+ grestore
+ } {
+ type 3 eq {
+ % Small arrows
+ gsave
+ .2 setlinewidth
+ x w 2 div add y h 2 div add M
+ w 4 div 0 rlineto
+ x w 4 div add y lineto stroke
+
+ x w 4 div add w 8 div add y h 4 div add M
+ x w 4 div add y lineto
+ w 4 div h 8 div rlineto stroke
+ grestore
+ } {
+ % do nothing
+ } ifelse
+ } ifelse
+} def
+
+% EPSF import.
+
+/BeginEPSF {
+ /b4_Inc_state save def % Save state for cleanup
+ /dict_count countdictstack def % Count objects on dict stack
+ /op_count count 1 sub def % Count objects on operand stack
+ userdict begin
+ /showpage { } def
+ 0 setgray 0 setlinecap
+ 1 setlinewidth 0 setlinejoin
+ 10 setmiterlimit [ ] 0 setdash newpath
+ /languagelevel where {
+ pop languagelevel
+ 1 ne {
+ false setstrokeadjust false setoverprint
+ } if
+ } if
+} bind def
+
+/EndEPSF {
+ count op_count sub { pos } repeat % Clean up stacks
+ countdictstack dict_count sub { end } repeat
+ b4_Inc_state restore
+} bind def
+
+% Check PostScript language level.
+/languagelevel where {
+ pop /gs_languagelevel languagelevel def
+} {
+ /gs_languagelevel 1 def
+} ifelse
+%%EndResource
+%%BeginResource: procset Enscript-Encoding-88591 1.6 1
+/encoding_vector [
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclam /quotedbl /numbersign
+/dollar /percent /ampersand /quoteright
+/parenleft /parenright /asterisk /plus
+/comma /hyphen /period /slash
+/zero /one /two /three
+/four /five /six /seven
+/eight /nine /colon /semicolon
+/less /equal /greater /question
+/at /A /B /C
+/D /E /F /G
+/H /I /J /K
+/L /M /N /O
+/P /Q /R /S
+/T /U /V /W
+/X /Y /Z /bracketleft
+/backslash /bracketright /asciicircum /underscore
+/quoteleft /a /b /c
+/d /e /f /g
+/h /i /j /k
+/l /m /n /o
+/p /q /r /s
+/t /u /v /w
+/x /y /z /braceleft
+/bar /braceright /tilde /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclamdown /cent /sterling
+/currency /yen /brokenbar /section
+/dieresis /copyright /ordfeminine /guillemotleft
+/logicalnot /hyphen /registered /macron
+/degree /plusminus /twosuperior /threesuperior
+/acute /mu /paragraph /bullet
+/cedilla /onesuperior /ordmasculine /guillemotright
+/onequarter /onehalf /threequarters /questiondown
+/Agrave /Aacute /Acircumflex /Atilde
+/Adieresis /Aring /AE /Ccedilla
+/Egrave /Eacute /Ecircumflex /Edieresis
+/Igrave /Iacute /Icircumflex /Idieresis
+/Eth /Ntilde /Ograve /Oacute
+/Ocircumflex /Otilde /Odieresis /multiply
+/Oslash /Ugrave /Uacute /Ucircumflex
+/Udieresis /Yacute /Thorn /germandbls
+/agrave /aacute /acircumflex /atilde
+/adieresis /aring /ae /ccedilla
+/egrave /eacute /ecircumflex /edieresis
+/igrave /iacute /icircumflex /idieresis
+/eth /ntilde /ograve /oacute
+/ocircumflex /otilde /odieresis /divide
+/oslash /ugrave /uacute /ucircumflex
+/udieresis /yacute /thorn /ydieresis
+] def
+%%EndResource
+%%EndProlog
+%%BeginSetup
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier
+/HFpt_w 10 def
+/HFpt_h 10 def
+/Courier-Bold /HF-gs-font MF
+/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
+/Courier /F-gs-font MF
+/F-gs-font 10 10 SF
+/#copies 1 def
+/d_page_w 520 def
+/d_page_h 747 def
+/d_header_x 0 def
+/d_header_y 747 def
+/d_header_w 520 def
+/d_header_h 0 def
+/d_footer_x 0 def
+/d_footer_y 0 def
+/d_footer_w 520 def
+/d_footer_h 0 def
+/d_output_w 520 def
+/d_output_h 747 def
+/cols 1 def
+userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
+ matrix invertmatrix matrix concatmatrix
+ matrix invertmatrix put
+%%EndSetup
+%%Page: (0,1) 1
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 1 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 701 M
+(Secure Shell Working Group J. Galbraith) s
+5 690 M
+(Internet-Draft VanDyke Software) s
+5 679 M
+(Expires: April 16, 2003 T. Ylonen) s
+5 668 M
+( S. Lehtinen) s
+5 657 M
+( SSH Communications Security Corp) s
+5 646 M
+( October 16, 2002) s
+5 613 M
+( SSH File Transfer Protocol) s
+5 602 M
+( draft-ietf-secsh-filexfer-03.txt) s
+5 580 M
+(Status of this Memo) s
+5 558 M
+( This document is an Internet-Draft and is in full conformance with) s
+5 547 M
+( all provisions of Section 10 of RFC2026.) s
+5 525 M
+( Internet-Drafts are working documents of the Internet Engineering) s
+5 514 M
+( Task Force \(IETF\), its areas, and its working groups. Note that) s
+5 503 M
+( other groups may also distribute working documents as Internet-) s
+5 492 M
+( Drafts.) s
+5 470 M
+( Internet-Drafts are draft documents valid for a maximum of six months) s
+5 459 M
+( and may be updated, replaced, or obsoleted by other documents at any) s
+5 448 M
+( time. It is inappropriate to use Internet-Drafts as reference) s
+5 437 M
+( material or to cite them other than as "work in progress.") s
+5 415 M
+( The list of current Internet-Drafts can be accessed at http://) s
+5 404 M
+( www.ietf.org/ietf/1id-abstracts.txt.) s
+5 382 M
+( The list of Internet-Draft Shadow Directories can be accessed at) s
+5 371 M
+( http://www.ietf.org/shadow.html.) s
+5 349 M
+( This Internet-Draft will expire on April 16, 2003.) s
+5 327 M
+(Copyright Notice) s
+5 305 M
+( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
+5 283 M
+(Abstract) s
+5 261 M
+( The SSH File Transfer Protocol provides secure file transfer) s
+5 250 M
+( functionality over any reliable data stream. It is the standard file) s
+5 239 M
+( transfer protocol for use with the SSH2 protocol. This document) s
+5 228 M
+( describes the file transfer protocol and its interface to the SSH2) s
+5 217 M
+( protocol suite.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 1]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 2 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(Table of Contents) s
+5 668 M
+( 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 657 M
+( 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4) s
+5 646 M
+( 3. General Packet Format . . . . . . . . . . . . . . . . . . 5) s
+5 635 M
+( 4. Protocol Initialization . . . . . . . . . . . . . . . . . 7) s
+5 624 M
+( 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 7) s
+5 613 M
+( 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 7) s
+5 602 M
+( 4.3 Determining Server Newline Convention . . . . . . . . . . 8) s
+5 591 M
+( 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 9) s
+5 580 M
+( 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 9) s
+5 569 M
+( 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 10) s
+5 558 M
+( 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 10) s
+5 547 M
+( 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 10) s
+5 536 M
+( 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 11) s
+5 525 M
+( 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 11) s
+5 514 M
+( 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 11) s
+5 503 M
+( 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 12) s
+5 492 M
+( 6. Requests From the Client to the Server . . . . . . . . . . 13) s
+5 481 M
+( 6.1 Request Synchronization and Reordering . . . . . . . . . . 13) s
+5 470 M
+( 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 14) s
+5 459 M
+( 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 14) s
+5 448 M
+( 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 17) s
+5 437 M
+( 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 18) s
+5 426 M
+( 6.6 Creating and Deleting Directories . . . . . . . . . . . . 19) s
+5 415 M
+( 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 19) s
+5 404 M
+( 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 20) s
+5 393 M
+( 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 21) s
+5 382 M
+( 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 22) s
+5 371 M
+( 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 23) s
+5 360 M
+( 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 23) s
+5 349 M
+( 7. Responses from the Server to the Client . . . . . . . . . 24) s
+5 338 M
+( 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 28) s
+5 327 M
+( 9. Security Considerations . . . . . . . . . . . . . . . . . 29) s
+5 316 M
+( 10. Changes from previous protocol versions . . . . . . . . . 30) s
+5 305 M
+( 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 30) s
+5 294 M
+( 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 31) s
+5 283 M
+( 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 31) s
+5 272 M
+( 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 31) s
+5 261 M
+( 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 32) s
+5 250 M
+( References . . . . . . . . . . . . . . . . . . . . . . . . 33) s
+5 239 M
+( Authors' Addresses . . . . . . . . . . . . . . . . . . . . 33) s
+5 228 M
+( Full Copyright Statement . . . . . . . . . . . . . . . . . 35) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 2]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (2,3) 2
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 3 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(1. Introduction) s
+5 668 M
+( This protocol provides secure file transfer \(and more generally file) s
+5 657 M
+( system access\) functionality over a reliable data stream, such as a) s
+5 646 M
+( channel in the SSH2 protocol [5].) s
+5 624 M
+( This protocol is designed so that it could be used to implement a) s
+5 613 M
+( secure remote file system service, as well as a secure file transfer) s
+5 602 M
+( service.) s
+5 580 M
+( This protocol assumes that it runs over a secure channel, and that) s
+5 569 M
+( the server has already authenticated the user at the client end, and) s
+5 558 M
+( that the identity of the client user is externally available to the) s
+5 547 M
+( server implementation.) s
+5 525 M
+( In general, this protocol follows a simple request-response model.) s
+5 514 M
+( Each request and response contains a sequence number and multiple) s
+5 503 M
+( requests may be pending simultaneously. There are a relatively large) s
+5 492 M
+( number of different request messages, but a small number of possible) s
+5 481 M
+( response messages. Each request has one or more response messages) s
+5 470 M
+( that may be returned in result \(e.g., a read either returns data or) s
+5 459 M
+( reports error status\).) s
+5 437 M
+( The packet format descriptions in this specification follow the) s
+5 426 M
+( notation presented in the secsh architecture draft. [5]) s
+5 404 M
+( Even though this protocol is described in the context of the SSH2) s
+5 393 M
+( protocol, this protocol is general and independent of the rest of the) s
+5 382 M
+( SSH2 protocol suite. It could be used in a number of different) s
+5 371 M
+( applications, such as secure file transfer over TLS RFC 2246 [1] and) s
+5 360 M
+( transfer of management information in VPN applications.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 3]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 4 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(2. Use with the SSH Connection Protocol) s
+5 668 M
+( When used with the SSH2 Protocol suite, this protocol is intended to) s
+5 657 M
+( be used from the SSH Connection Protocol [7] as a subsystem, as) s
+5 646 M
+( described in section ``Starting a Shell or a Command''. The) s
+5 635 M
+( subsystem name used with this protocol is "sftp".) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 4]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (4,5) 3
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 5 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(3. General Packet Format) s
+5 668 M
+( All packets transmitted over the secure connection are of the) s
+5 657 M
+( following format:) s
+5 635 M
+( uint32 length) s
+5 624 M
+( byte type) s
+5 613 M
+( byte[length - 1] data payload) s
+5 591 M
+( That is, they are just data preceded by 32-bit length and 8-bit type) s
+5 580 M
+( fields. The `length' is the length of the data area, and does not) s
+5 569 M
+( include the `length' field itself. The format and interpretation of) s
+5 558 M
+( the data area depends on the packet type.) s
+5 536 M
+( All packet descriptions below only specify the packet type and the) s
+5 525 M
+( data that goes into the data field. Thus, they should be prefixed by) s
+5 514 M
+( the `length' and `type' fields.) s
+5 492 M
+( The maximum size of a packet is in practice determined by the client) s
+5 481 M
+( \(the maximum size of read or write requests that it sends, plus a few) s
+5 470 M
+( bytes of packet overhead\). All servers SHOULD support packets of at) s
+5 459 M
+( least 34000 bytes \(where the packet size refers to the full length,) s
+5 448 M
+( including the header above\). This should allow for reads and writes) s
+5 437 M
+( of at most 32768 bytes.) s
+5 415 M
+( There is no limit on the number of outstanding \(non-acknowledged\)) s
+5 404 M
+( requests that the client may send to the server. In practice this is) s
+5 393 M
+( limited by the buffering available on the data stream and the queuing) s
+5 382 M
+( performed by the server. If the server's queues are full, it should) s
+5 371 M
+( not read any more data from the stream, and flow control will prevent) s
+5 360 M
+( the client from sending more requests. Note, however, that while) s
+5 349 M
+( there is no restriction on the protocol level, the client's API may) s
+5 338 M
+( provide a limit in order to prevent infinite queuing of outgoing) s
+5 327 M
+( requests at the client.) s
+5 305 M
+( The following values are defined for packet types.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 5]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 6 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( #define SSH_FXP_INIT 1) s
+5 679 M
+( #define SSH_FXP_VERSION 2) s
+5 668 M
+( #define SSH_FXP_OPEN 3) s
+5 657 M
+( #define SSH_FXP_CLOSE 4) s
+5 646 M
+( #define SSH_FXP_READ 5) s
+5 635 M
+( #define SSH_FXP_WRITE 6) s
+5 624 M
+( #define SSH_FXP_LSTAT 7) s
+5 613 M
+( #define SSH_FXP_FSTAT 8) s
+5 602 M
+( #define SSH_FXP_SETSTAT 9) s
+5 591 M
+( #define SSH_FXP_FSETSTAT 10) s
+5 580 M
+( #define SSH_FXP_OPENDIR 11) s
+5 569 M
+( #define SSH_FXP_READDIR 12) s
+5 558 M
+( #define SSH_FXP_REMOVE 13) s
+5 547 M
+( #define SSH_FXP_MKDIR 14) s
+5 536 M
+( #define SSH_FXP_RMDIR 15) s
+5 525 M
+( #define SSH_FXP_REALPATH 16) s
+5 514 M
+( #define SSH_FXP_STAT 17) s
+5 503 M
+( #define SSH_FXP_RENAME 18) s
+5 492 M
+( #define SSH_FXP_READLINK 19) s
+5 481 M
+( #define SSH_FXP_SYMLINK 20) s
+5 459 M
+( #define SSH_FXP_STATUS 101) s
+5 448 M
+( #define SSH_FXP_HANDLE 102) s
+5 437 M
+( #define SSH_FXP_DATA 103) s
+5 426 M
+( #define SSH_FXP_NAME 104) s
+5 415 M
+( #define SSH_FXP_ATTRS 105) s
+5 393 M
+( #define SSH_FXP_EXTENDED 200) s
+5 382 M
+( #define SSH_FXP_EXTENDED_REPLY 201) s
+5 360 M
+( RESERVED_FOR_EXTENSIONS 210-255) s
+5 338 M
+( Additional packet types should only be defined if the protocol) s
+5 327 M
+( version number \(see Section ``Protocol Initialization''\) is) s
+5 316 M
+( incremented, and their use MUST be negotiated using the version) s
+5 305 M
+( number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY) s
+5 294 M
+( packets can be used to implement vendor-specific extensions. See) s
+5 283 M
+( Section ``Vendor-Specific-Extensions'' for more details.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 6]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (6,7) 4
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 7 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(4. Protocol Initialization) s
+5 668 M
+( When the file transfer protocol starts, the client first sends a) s
+5 657 M
+( SSH_FXP_INIT \(including its version number\) packet to the server.) s
+5 646 M
+( The server responds with a SSH_FXP_VERSION packet, supplying the) s
+5 635 M
+( lowest of its own and the client's version number. Both parties) s
+5 624 M
+( should from then on adhere to particular version of the protocol.) s
+5 602 M
+( The version number of the protocol specified in this document is 4.) s
+5 591 M
+( The version number should be incremented for each incompatible) s
+5 580 M
+( revision of this protocol.) s
+5 558 M
+(4.1 Client Initialization) s
+5 536 M
+( The SSH_FXP_INIT packet \(from client to server\) has the following) s
+5 525 M
+( data:) s
+5 503 M
+( uint32 version) s
+5 481 M
+( Version 3 of this protocol allowed clients to include extensions in) s
+5 470 M
+( the SSH_FXP_INIT packet; however, this can cause interoperability) s
+5 459 M
+( problems with version 1 and version 2 servers because the client must) s
+5 448 M
+( send this packet before knowing the servers version.) s
+5 426 M
+( In this version of the protocol, clients MUST use the) s
+5 415 M
+( SSH_FXP_EXTENDED packet to send extensions to the server after) s
+5 404 M
+( version exchange has completed. Clients MUST NOT include extensions) s
+5 393 M
+( in the version packet. This will prevent interoperability problems) s
+5 382 M
+( with older servers) s
+5 360 M
+(4.2 Server Initialization) s
+5 338 M
+( The SSH_FXP_VERSION packet \(from server to client\) has the following) s
+5 327 M
+( data:) s
+5 305 M
+( uint32 version) s
+5 294 M
+( <extension data>) s
+5 272 M
+( 'version' is the lower of the protocol version supported by the) s
+5 261 M
+( server and the version number received from the client.) s
+5 239 M
+( The extension data may be empty, or may be a sequence of) s
+5 217 M
+( string extension_name) s
+5 206 M
+( string extension_data) s
+5 184 M
+( pairs \(both strings MUST always be present if one is, but the) s
+5 173 M
+( `extension_data' string may be of zero length\). If present, these) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 7]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 8 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( strings indicate extensions to the baseline protocol. The) s
+5 679 M
+( `extension_name' field\(s\) identify the name of the extension. The) s
+5 668 M
+( name should be of the form "name@domain", where the domain is the DNS) s
+5 657 M
+( domain name of the organization defining the extension. Additional) s
+5 646 M
+( names that are not of this format may be defined later by the IETF.) s
+5 635 M
+( Implementations MUST silently ignore any extensions whose name they) s
+5 624 M
+( do not recognize.) s
+5 602 M
+(4.3 Determining Server Newline Convention) s
+5 580 M
+( In order to correctly process text files in a cross platform) s
+5 569 M
+( compatible way, the newline convention must be converted from that of) s
+5 558 M
+( the server to that of the client, or, during an upload, from that of) s
+5 547 M
+( the client to that of the server.) s
+5 525 M
+( Versions 3 and prior of this protocol made no provisions for) s
+5 514 M
+( processing text files. Many clients implemented some sort of) s
+5 503 M
+( conversion algorithm, but without either a 'canonical' on the wire) s
+5 492 M
+( format or knowledge of the servers newline convention, correct) s
+5 481 M
+( conversion was not always possible.) s
+5 459 M
+( Starting with Version 4, the SSH_FXF_TEXT file open flag \(Section) s
+5 448 M
+( 6.3\) makes it possible to request that the server translate a file to) s
+5 437 M
+( a 'canonical' on the wire format. This format uses \\r\\n as the line) s
+5 426 M
+( separator.) s
+5 404 M
+( Servers for systems using multiple newline characters \(for example,) s
+5 393 M
+( Mac OS X or VMS\) or systems using counted records, MUST translate to) s
+5 382 M
+( the canonical form.) s
+5 360 M
+( However, to ease the burden of implementation on servers that use a) s
+5 349 M
+( single, simple separator sequence, the following extension allows the) s
+5 338 M
+( canonical format to be changed.) s
+5 316 M
+( string "newline") s
+5 305 M
+( string new-canonical-separator \(usually "\\r" or "\\n" or "\\r\\n"\)) s
+5 283 M
+( All clients MUST support this extension.) s
+5 261 M
+( When processing text files, clients SHOULD NOT translate any) s
+5 250 M
+( character or sequence that is not an exact match of the servers) s
+5 239 M
+( newline separator.) s
+5 217 M
+( In particular, if the newline sequence being used is the canonical) s
+5 206 M
+( "\\r\\n" sequence, a lone \\r or a lone \\n SHOULD be written through) s
+5 195 M
+( without change.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 8]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (8,9) 5
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 9 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(5. File Attributes) s
+5 668 M
+( A new compound data type is defined for encoding file attributes.) s
+5 657 M
+( The same encoding is used both when returning file attributes from) s
+5 646 M
+( the server and when sending file attributes to the server. When) s
+5 635 M
+( sending it to the server, the flags field specifies which attributes) s
+5 624 M
+( are included, and the server will use default values for the) s
+5 613 M
+( remaining attributes \(or will not modify the values of remaining) s
+5 602 M
+( attributes\). When receiving attributes from the server, the flags) s
+5 591 M
+( specify which attributes are included in the returned data. The) s
+5 580 M
+( server normally returns all attributes it knows about.) s
+5 558 M
+( uint32 flags) s
+5 547 M
+( byte type always present) s
+5 536 M
+( uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE) s
+5 525 M
+( string owner present only if flag SSH_FILEXFER_ATTR_OWNERGROUP) s
+5 514 M
+( string group present only if flag SSH_FILEXFER_ATTR_OWNERGROUP) s
+5 503 M
+( uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS) s
+5 492 M
+( uint32 atime present only if flag SSH_FILEXFER_ATTR_ACCESSTIME) s
+5 481 M
+( uint32 createtime present only if flag SSH_FILEXFER_ATTR_CREATETIME) s
+5 470 M
+( uint32 mtime present only if flag SSH_FILEXFER_ATTR_MODIFYTIME) s
+5 459 M
+( string acl present only if flag SSH_FILEXFER_ATTR_ACL) s
+5 448 M
+( uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED) s
+5 437 M
+( string extended_type) s
+5 426 M
+( string extended_data) s
+5 415 M
+( ... more extended data \(extended_type - extended_data pairs\),) s
+5 404 M
+( so that number of pairs equals extended_count) s
+5 371 M
+(5.1 Flags) s
+5 349 M
+( The `flags' specify which of the fields are present. Those fields) s
+5 338 M
+( for which the corresponding flag is not set are not present \(not) s
+5 327 M
+( included in the packet\). New flags can only be added by incrementing) s
+5 316 M
+( the protocol version number \(or by using the extension mechanism) s
+5 305 M
+( described below\).) s
+5 283 M
+( The flags bits are defined to have the following values:) s
+5 261 M
+( #define SSH_FILEXFER_ATTR_SIZE 0x00000001) s
+5 250 M
+( #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004) s
+5 239 M
+( #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008) s
+5 228 M
+( #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010) s
+5 217 M
+( #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020) s
+5 206 M
+( #define SSH_FILEXFER_ATTR_ACL 0x00000040) s
+5 195 M
+( #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080) s
+5 184 M
+( #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 9]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 10 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( In previous versions of this protocol flags value 0x00000002 was) s
+5 679 M
+( SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP) s
+5 668 M
+( was given a new value in order to ease implementation burden.) s
+5 657 M
+( 0x00000002 MUST NOT appear in the mask. Some future version of this) s
+5 646 M
+( protocol may reuse flag 0x00000002.) s
+5 624 M
+(5.2 Type) s
+5 602 M
+( The type field is always present. The following types are defined:) s
+5 580 M
+( #define SSH_FILEXFER_TYPE_REGULAR 1) s
+5 569 M
+( #define SSH_FILEXFER_TYPE_DIRECTORY 2) s
+5 558 M
+( #define SSH_FILEXFER_TYPE_SYMLINK 3) s
+5 547 M
+( #define SSH_FILEXFER_TYPE_SPECIAL 4) s
+5 536 M
+( #define SSH_FILEXFER_TYPE_UNKNOWN 5) s
+5 514 M
+( On a POSIX system, these values would be derived from the permission) s
+5 503 M
+( field.) s
+5 481 M
+(5.3 Size) s
+5 459 M
+( The `size' field specifies the size of the file on disk, in bytes.) s
+5 448 M
+( If it is present during file creation, it should be considered a hint) s
+5 437 M
+( as to the files eventual size.) s
+5 415 M
+( Files opened with the SSH_FXF_TEXT flag may have a size that is) s
+5 404 M
+( greater or less than the value of the size field.) s
+5 382 M
+(5.4 Owner and Group) s
+5 360 M
+( The `owner' and `group' fields are represented as UTF-8 strings; this) s
+5 349 M
+( is the form used by NFS v4. See NFS version 4 Protocol. [3] The) s
+5 338 M
+( following text is selected quotations from section 5.6.) s
+5 316 M
+( To avoid a representation that is tied to a particular underlying) s
+5 305 M
+( implementation at the client or server, the use of UTF-8 strings has) s
+5 294 M
+( been chosen. The string should be of the form user@dns_domain".) s
+5 283 M
+( This will allow for a client and server that do not use the same) s
+5 272 M
+( local representation the ability to translate to a common syntax that) s
+5 261 M
+( can be interpreted by both. In the case where there is no) s
+5 250 M
+( translation available to the client or server, the attribute value) s
+5 239 M
+( must be constructed without the "@". Therefore, the absence of the @) s
+5 228 M
+( from the owner or owner_group attribute signifies that no translation) s
+5 217 M
+( was available and the receiver of the attribute should not place any) s
+5 206 M
+( special meaning with the attribute value. Even though the attribute) s
+5 195 M
+( value can not be translated, it may still be useful. In the case of) s
+5 184 M
+( a client, the attribute string may be used for local display of) s
+5 173 M
+( ownership.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 10]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (10,11) 6
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 11 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(5.5 Permissions) s
+5 668 M
+( The `permissions' field contains a bit mask of file permissions as) s
+5 657 M
+( defined by POSIX [1].) s
+5 635 M
+(5.6 Times) s
+5 613 M
+( The 'atime', 'createtime', and 'mtime' contain the access, creation,) s
+5 602 M
+( and modification times of the files, respectively. They are) s
+5 591 M
+( represented as seconds from Jan 1, 1970 in UTC.) s
+5 569 M
+(5.7 ACL) s
+5 547 M
+( The 'ACL' field contains an ACL similar to that defined in section) s
+5 536 M
+( 5.9 of NFS version 4 Protocol [3].) s
+5 514 M
+( uint32 ace-count) s
+5 492 M
+( repeated ace-count time:) s
+5 481 M
+( uint32 ace-type) s
+5 470 M
+( uint32 ace-flag) s
+5 459 M
+( uint32 ace-mask) s
+5 448 M
+( string who [UTF-8]) s
+5 426 M
+( ace-type is one of the following four values \(taken from NFS Version) s
+5 415 M
+( 4 Protocol [3]:) s
+5 393 M
+( const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;) s
+5 382 M
+( const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;) s
+5 371 M
+( const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;) s
+5 360 M
+( const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;) s
+5 338 M
+( ace-flag is a combination of the following flag values. See NFS) s
+5 327 M
+( Version 4 Protocol [3] section 5.9.2:) s
+5 305 M
+( const ACE4_FILE_INHERIT_ACE = 0x00000001;) s
+5 294 M
+( const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;) s
+5 283 M
+( const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;) s
+5 272 M
+( const ACE4_INHERIT_ONLY_ACE = 0x00000008;) s
+5 261 M
+( const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;) s
+5 250 M
+( const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;) s
+5 239 M
+( const ACE4_IDENTIFIER_GROUP = 0x00000040;) s
+5 217 M
+( ace-mask is any combination of the following flags \(taken from NFS) s
+5 206 M
+( Version 4 Protocol [3] section 5.9.3:) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 11]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 12 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( const ACE4_READ_DATA = 0x00000001;) s
+5 679 M
+( const ACE4_LIST_DIRECTORY = 0x00000001;) s
+5 668 M
+( const ACE4_WRITE_DATA = 0x00000002;) s
+5 657 M
+( const ACE4_ADD_FILE = 0x00000002;) s
+5 646 M
+( const ACE4_APPEND_DATA = 0x00000004;) s
+5 635 M
+( const ACE4_ADD_SUBDIRECTORY = 0x00000004;) s
+5 624 M
+( const ACE4_READ_NAMED_ATTRS = 0x00000008;) s
+5 613 M
+( const ACE4_WRITE_NAMED_ATTRS = 0x00000010;) s
+5 602 M
+( const ACE4_EXECUTE = 0x00000020;) s
+5 591 M
+( const ACE4_DELETE_CHILD = 0x00000040;) s
+5 580 M
+( const ACE4_READ_ATTRIBUTES = 0x00000080;) s
+5 569 M
+( const ACE4_WRITE_ATTRIBUTES = 0x00000100;) s
+5 558 M
+( const ACE4_DELETE = 0x00010000;) s
+5 547 M
+( const ACE4_READ_ACL = 0x00020000;) s
+5 536 M
+( const ACE4_WRITE_ACL = 0x00040000;) s
+5 525 M
+( const ACE4_WRITE_OWNER = 0x00080000;) s
+5 514 M
+( const ACE4_SYNCHRONIZE = 0x00100000;) s
+5 492 M
+( who is a UTF-8 string of the form described in 'Owner and Group') s
+5 481 M
+( \(Section 5.4\)) s
+5 459 M
+(5.8 Extended attributes) s
+5 437 M
+( The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension) s
+5 426 M
+( mechanism for vendor-specific extensions. If the flag is specified,) s
+5 415 M
+( then the `extended_count' field is present. It specifies the number) s
+5 404 M
+( of extended_type-extended_data pairs that follow. Each of these) s
+5 393 M
+( pairs specifies an extended attribute. For each of the attributes,) s
+5 382 M
+( the extended_type field should be a string of the format) s
+5 371 M
+( "name@domain", where "domain" is a valid, registered domain name and) s
+5 360 M
+( "name" identifies the method. The IETF may later standardize certain) s
+5 349 M
+( names that deviate from this format \(e.g., that do not contain the) s
+5 338 M
+( "@" sign\). The interpretation of `extended_data' depends on the) s
+5 327 M
+( type. Implementations SHOULD ignore extended data fields that they) s
+5 316 M
+( do not understand.) s
+5 294 M
+( Additional fields can be added to the attributes by either defining) s
+5 283 M
+( additional bits to the flags field to indicate their presence, or by) s
+5 272 M
+( defining extended attributes for them. The extended attributes) s
+5 261 M
+( mechanism is recommended for most purposes; additional flags bits) s
+5 250 M
+( should only be defined by an IETF standards action that also) s
+5 239 M
+( increments the protocol version number. The use of such new fields) s
+5 228 M
+( MUST be negotiated by the version number in the protocol exchange.) s
+5 217 M
+( It is a protocol error if a packet with unsupported protocol bits is) s
+5 206 M
+( received.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 12]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (12,13) 7
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 13 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(6. Requests From the Client to the Server) s
+5 668 M
+( Requests from the client to the server represent the various file) s
+5 657 M
+( system operations. Each request begins with an `id' field, which is) s
+5 646 M
+( a 32-bit identifier identifying the request \(selected by the client\).) s
+5 635 M
+( The same identifier will be returned in the response to the request.) s
+5 624 M
+( One possible implementation is a monotonically increasing request) s
+5 613 M
+( sequence number \(modulo 2^32\).) s
+5 591 M
+( Many operations in the protocol operate on open files. The) s
+5 580 M
+( SSH_FXP_OPEN request can return a file handle \(which is an opaque) s
+5 569 M
+( variable-length string\) which may be used to access the file later) s
+5 558 M
+( \(e.g. in a read operation\). The client MUST NOT send requests the) s
+5 547 M
+( server with bogus or closed handles. However, the server MUST) s
+5 536 M
+( perform adequate checks on the handle in order to avoid security) s
+5 525 M
+( risks due to fabricated handles.) s
+5 503 M
+( This design allows either stateful and stateless server) s
+5 492 M
+( implementation, as well as an implementation which caches state) s
+5 481 M
+( between requests but may also flush it. The contents of the file) s
+5 470 M
+( handle string are entirely up to the server and its design. The) s
+5 459 M
+( client should not modify or attempt to interpret the file handle) s
+5 448 M
+( strings.) s
+5 426 M
+( The file handle strings MUST NOT be longer than 256 bytes.) s
+5 404 M
+(6.1 Request Synchronization and Reordering) s
+5 382 M
+( The protocol and implementations MUST process requests relating to) s
+5 371 M
+( the same file in the order in which they are received. In other) s
+5 360 M
+( words, if an application submits multiple requests to the server, the) s
+5 349 M
+( results in the responses will be the same as if it had sent the) s
+5 338 M
+( requests one at a time and waited for the response in each case. For) s
+5 327 M
+( example, the server may process non-overlapping read/write requests) s
+5 316 M
+( to the same file in parallel, but overlapping reads and writes cannot) s
+5 305 M
+( be reordered or parallelized. However, there are no ordering) s
+5 294 M
+( restrictions on the server for processing requests from two different) s
+5 283 M
+( file transfer connections. The server may interleave and parallelize) s
+5 272 M
+( them at will.) s
+5 250 M
+( There are no restrictions on the order in which responses to) s
+5 239 M
+( outstanding requests are delivered to the client, except that the) s
+5 228 M
+( server must ensure fairness in the sense that processing of no) s
+5 217 M
+( request will be indefinitely delayed even if the client is sending) s
+5 206 M
+( other requests so that there are multiple outstanding requests all) s
+5 195 M
+( the time.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 13]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 14 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(6.2 File Names) s
+5 668 M
+( This protocol represents file names as strings. File names are) s
+5 657 M
+( assumed to use the slash \('/'\) character as a directory separator.) s
+5 635 M
+( File names starting with a slash are "absolute", and are relative to) s
+5 624 M
+( the root of the file system. Names starting with any other character) s
+5 613 M
+( are relative to the user's default directory \(home directory\). Note) s
+5 602 M
+( that identifying the user is assumed to take place outside of this) s
+5 591 M
+( protocol.) s
+5 569 M
+( Servers SHOULD interpret a path name component ".." as referring to) s
+5 558 M
+( the parent directory, and "." as referring to the current directory.) s
+5 547 M
+( If the server implementation limits access to certain parts of the) s
+5 536 M
+( file system, it must be extra careful in parsing file names when) s
+5 525 M
+( enforcing such restrictions. There have been numerous reported) s
+5 514 M
+( security bugs where a ".." in a path name has allowed access outside) s
+5 503 M
+( the intended area.) s
+5 481 M
+( An empty path name is valid, and it refers to the user's default) s
+5 470 M
+( directory \(usually the user's home directory\).) s
+5 448 M
+( Otherwise, no syntax is defined for file names by this specification.) s
+5 437 M
+( Clients should not make any other assumptions; however, they can) s
+5 426 M
+( splice path name components returned by SSH_FXP_READDIR together) s
+5 415 M
+( using a slash \('/'\) as the separator, and that will work as expected.) s
+5 393 M
+( In order to comply with IETF Policy on Character Sets and Languages) s
+5 382 M
+( [2], all filenames are to be encoded in UTF-8. The shortest valid) s
+5 371 M
+( UTF-8 encoding of the UNICODE data MUST be used. The server is) s
+5 360 M
+( responsible for converting the UNICODE data to whatever canonical) s
+5 349 M
+( form it requires.) s
+5 327 M
+( For example, if the server requires that precomposed characters) s
+5 316 M
+( always be used, the server MUST NOT assume the filename as sent by) s
+5 305 M
+( the client has this attribute, but must do this normalization itself.) s
+5 283 M
+( It is understood that the lack of well-defined semantics for file) s
+5 272 M
+( names may cause interoperability problems between clients and servers) s
+5 261 M
+( using radically different operating systems. However, this approach) s
+5 250 M
+( is known to work acceptably with most systems, and alternative) s
+5 239 M
+( approaches that e.g. treat file names as sequences of structured) s
+5 228 M
+( components are quite complicated.) s
+5 206 M
+(6.3 Opening, Creating, and Closing Files) s
+5 184 M
+( Files are opened and created using the SSH_FXP_OPEN message, whose) s
+5 173 M
+( data part is as follows:) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 14]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (14,15) 8
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 15 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( uint32 id) s
+5 679 M
+( string filename [UTF-8]) s
+5 668 M
+( uint32 pflags) s
+5 657 M
+( ATTRS attrs) s
+5 635 M
+( The `id' field is the request identifier as for all requests.) s
+5 613 M
+( The `filename' field specifies the file name. See Section ``File) s
+5 602 M
+( Names'' for more information.) s
+5 580 M
+( The `pflags' field is a bitmask. The following bits have been) s
+5 569 M
+( defined.) s
+5 547 M
+( #define SSH_FXF_READ 0x00000001) s
+5 536 M
+( #define SSH_FXF_WRITE 0x00000002) s
+5 525 M
+( #define SSH_FXF_APPEND 0x00000004) s
+5 514 M
+( #define SSH_FXF_CREAT 0x00000008) s
+5 503 M
+( #define SSH_FXF_TRUNC 0x00000010) s
+5 492 M
+( #define SSH_FXF_EXCL 0x00000020) s
+5 481 M
+( #define SSH_FXF_TEXT 0x00000040) s
+5 459 M
+( These have the following meanings:) s
+5 437 M
+( SSH_FXF_READ) s
+5 426 M
+( Open the file for reading.) s
+5 404 M
+( SSH_FXF_WRITE) s
+5 393 M
+( Open the file for writing. If both this and SSH_FXF_READ are) s
+5 382 M
+( specified, the file is opened for both reading and writing.) s
+5 360 M
+( SSH_FXF_APPEND) s
+5 349 M
+( Force all writes to append data at the end of the file. The) s
+5 338 M
+( offset parameter to write will be ignored.) s
+5 316 M
+( SSH_FXF_CREAT) s
+5 305 M
+( If this flag is specified, then a new file will be created if one) s
+5 294 M
+( does not already exist \(if O_TRUNC is specified, the new file will) s
+5 283 M
+( be truncated to zero length if it previously exists\).) s
+5 261 M
+( SSH_FXF_TRUNC) s
+5 250 M
+( Forces an existing file with the same name to be truncated to zero) s
+5 239 M
+( length when creating a file by specifying SSH_FXF_CREAT.) s
+5 228 M
+( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
+5 206 M
+( SSH_FXF_EXCL) s
+5 195 M
+( Causes the request to fail if the named file already exists.) s
+5 184 M
+( SSH_FXF_CREAT MUST also be specified if this flag is used.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 15]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 16 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( SSH_FXF_TEXT) s
+5 679 M
+( Indicates that the server should treat the file as text and) s
+5 668 M
+( convert it to the canonical newline convention in use. \(See) s
+5 657 M
+( Determining Server Newline Convention. \(Section 4.3\)) s
+5 635 M
+( When a file is opened with the FXF_TEXT flag, the offset field in) s
+5 624 M
+( both the read and write function are ignored.) s
+5 602 M
+( Servers MUST correctly process multiple parallel reads and writes) s
+5 591 M
+( correctly in this mode. Naturally, it is permissible for them to) s
+5 580 M
+( do this by serializing the requests. It would not be possible for) s
+5 569 M
+( a client to reliably detect a server that does not implement) s
+5 558 M
+( parallel writes in time to prevent damage.) s
+5 536 M
+( Clients SHOULD use the SSH_FXF_APPEND flag to append data to a) s
+5 525 M
+( text file rather then using write with a calculated offset.) s
+5 503 M
+( To support seeks on text file the following SSH_FXP_EXTENDED) s
+5 492 M
+( packet is defined.) s
+5 448 M
+( string "text-seek") s
+5 437 M
+( string file-handle) s
+5 426 M
+( uint64 line-number) s
+5 404 M
+( line-number is the index of the line number to seek to, where byte) s
+5 393 M
+( 0 in the file is line number 0, and the byte directly following) s
+5 382 M
+( the first newline sequence in the file is line number 1 and so on.) s
+5 360 M
+( The response to a "text-seek" request is an SSH_FXP_STATUS) s
+5 349 M
+( message.) s
+5 327 M
+( An attempt to seek past the end-of-file should result in a) s
+5 316 M
+( SSH_FX_EOF status.) s
+5 294 M
+( Servers SHOULD support at least one "text-seek" in order to) s
+5 283 M
+( support resume. However, a client MUST be prepared to receive) s
+5 272 M
+( SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation.) s
+5 261 M
+( The client can then try a fall-back strategy, if it has one.) s
+5 239 M
+( Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned) s
+5 228 M
+( for read or write operations that are not sequential.) s
+5 206 M
+( The `attrs' field specifies the initial attributes for the file.) s
+5 195 M
+( Default values will be used for those attributes that are not) s
+5 184 M
+( specified. See Section ``File Attributes'' for more information.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 16]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (16,17) 9
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 17 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( The response to this message will be either SSH_FXP_HANDLE \(if the) s
+5 679 M
+( operation is successful\) or SSH_FXP_STATUS \(if the operation fails\).) s
+5 657 M
+( A file is closed by using the SSH_FXP_CLOSE request. Its data field) s
+5 646 M
+( has the following format:) s
+5 624 M
+( uint32 id) s
+5 613 M
+( string handle) s
+5 591 M
+( where `id' is the request identifier, and `handle' is a handle) s
+5 580 M
+( previously returned in the response to SSH_FXP_OPEN or) s
+5 569 M
+( SSH_FXP_OPENDIR. The handle becomes invalid immediately after this) s
+5 558 M
+( request has been sent.) s
+5 536 M
+( The response to this request will be a SSH_FXP_STATUS message. One) s
+5 525 M
+( should note that on some server platforms even a close can fail.) s
+5 514 M
+( This can happen e.g. if the server operating system caches writes,) s
+5 503 M
+( and an error occurs while flushing cached writes during the close.) s
+5 481 M
+(6.4 Reading and Writing) s
+5 459 M
+( Once a file has been opened, it can be read using the SSH_FXP_READ) s
+5 448 M
+( message, which has the following format:) s
+5 426 M
+( uint32 id) s
+5 415 M
+( string handle) s
+5 404 M
+( uint64 offset) s
+5 393 M
+( uint32 len) s
+5 371 M
+( where `id' is the request identifier, `handle' is an open file handle) s
+5 360 M
+( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) relative) s
+5 349 M
+( to the beginning of the file from where to start reading, and `len') s
+5 338 M
+( is the maximum number of bytes to read.) s
+5 316 M
+( In response to this request, the server will read as many bytes as it) s
+5 305 M
+( can from the file \(up to `len'\), and return them in a SSH_FXP_DATA) s
+5 294 M
+( message. If an error occurs or EOF is encountered before reading any) s
+5 283 M
+( data, the server will respond with SSH_FXP_STATUS. For normal disk) s
+5 272 M
+( files, it is guaranteed that this will read the specified number of) s
+5 261 M
+( bytes, or up to end of file. For e.g. device files this may return) s
+5 250 M
+( fewer bytes than requested.) s
+5 228 M
+( Writing to a file is achieved using the SSH_FXP_WRITE message, which) s
+5 217 M
+( has the following format:) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 17]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 18 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( uint32 id) s
+5 679 M
+( string handle) s
+5 668 M
+( uint64 offset) s
+5 657 M
+( string data) s
+5 635 M
+( where `id' is a request identifier, `handle' is a file handle) s
+5 624 M
+( returned by SSH_FXP_OPEN, `offset' is the offset \(in bytes\) from the) s
+5 613 M
+( beginning of the file where to start writing, and `data' is the data) s
+5 602 M
+( to be written.) s
+5 580 M
+( The write will extend the file if writing beyond the end of the file.) s
+5 569 M
+( It is legal to write way beyond the end of the file; the semantics) s
+5 558 M
+( are to write zeroes from the end of the file to the specified offset) s
+5 547 M
+( and then the data. On most operating systems, such writes do not) s
+5 536 M
+( allocate disk space but instead leave "holes" in the file.) s
+5 514 M
+( The server responds to a write request with a SSH_FXP_STATUS message.) s
+5 492 M
+(6.5 Removing and Renaming Files) s
+5 470 M
+( Files can be removed using the SSH_FXP_REMOVE message. It has the) s
+5 459 M
+( following format:) s
+5 437 M
+( uint32 id) s
+5 426 M
+( string filename [UTF-8]) s
+5 404 M
+( where `id' is the request identifier and `filename' is the name of) s
+5 393 M
+( the file to be removed. See Section ``File Names'' for more) s
+5 382 M
+( information. This request cannot be used to remove directories.) s
+5 360 M
+( The server will respond to this request with a SSH_FXP_STATUS) s
+5 349 M
+( message.) s
+5 327 M
+( Files \(and directories\) can be renamed using the SSH_FXP_RENAME) s
+5 316 M
+( message. Its data is as follows:) s
+5 294 M
+( uint32 id) s
+5 283 M
+( string oldpath [UTF-8]) s
+5 272 M
+( string newpath [UTF-8]) s
+5 250 M
+( where `id' is the request identifier, `oldpath' is the name of an) s
+5 239 M
+( existing file or directory, and `newpath' is the new name for the) s
+5 228 M
+( file or directory. It is an error if there already exists a file) s
+5 217 M
+( with the name specified by newpath. The server may also fail rename) s
+5 206 M
+( requests in other situations, for example if `oldpath' and `newpath') s
+5 195 M
+( point to different file systems on the server.) s
+5 173 M
+( The server will respond to this request with a SSH_FXP_STATUS) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 18]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (18,19) 10
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 19 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( message.) s
+5 668 M
+(6.6 Creating and Deleting Directories) s
+5 646 M
+( New directories can be created using the SSH_FXP_MKDIR request. It) s
+5 635 M
+( has the following format:) s
+5 613 M
+( uint32 id) s
+5 602 M
+( string path [UTF-8]) s
+5 591 M
+( ATTRS attrs) s
+5 569 M
+( where `id' is the request identifier.) s
+5 547 M
+( `path' specifies the directory to be created. See Section ``File) s
+5 536 M
+( Names'' for more information on file names.) s
+5 514 M
+( `attrs' specifies the attributes that should be applied to it upon) s
+5 503 M
+( creation. Attributes are discussed in more detail in Section ``File) s
+5 492 M
+( Attributes''.) s
+5 470 M
+( The server will respond to this request with a SSH_FXP_STATUS) s
+5 459 M
+( message. If a file or directory with the specified path already) s
+5 448 M
+( exists, an error will be returned.) s
+5 426 M
+( Directories can be removed using the SSH_FXP_RMDIR request, which has) s
+5 415 M
+( the following format:) s
+5 393 M
+( uint32 id) s
+5 382 M
+( string path [UTF-8]) s
+5 360 M
+( where `id' is the request identifier, and `path' specifies the) s
+5 349 M
+( directory to be removed. See Section ``File Names'' for more) s
+5 338 M
+( information on file names.) s
+5 316 M
+( The server responds to this request with a SSH_FXP_STATUS message.) s
+5 305 M
+( Errors may be returned from this operation for various reasons,) s
+5 294 M
+( including, but not limited to, the path does not exist, the path does) s
+5 283 M
+( not refer to a directory object, the directory is not empty, or the) s
+5 272 M
+( user has insufficient access or permission to perform the requested) s
+5 261 M
+( operation.) s
+5 239 M
+(6.7 Scanning Directories) s
+5 217 M
+( The files in a directory can be listed using the SSH_FXP_OPENDIR and) s
+5 206 M
+( SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one) s
+5 195 M
+( or more file names with full file attributes for each file. The) s
+5 184 M
+( client should call SSH_FXP_READDIR repeatedly until it has found the) s
+5 173 M
+( file it is looking for or until the server responds with a) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 19]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 20 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( SSH_FXP_STATUS message indicating an error \(normally SSH_FX_EOF if) s
+5 679 M
+( there are no more files in the directory\). The client should then) s
+5 668 M
+( close the handle using the SSH_FXP_CLOSE request.) s
+5 646 M
+( The SSH_FXP_OPENDIR opens a directory for reading. It has the) s
+5 635 M
+( following format:) s
+5 613 M
+( uint32 id) s
+5 602 M
+( string path [UTF-8]) s
+5 580 M
+( where `id' is the request identifier and `path' is the path name of) s
+5 569 M
+( the directory to be listed \(without any trailing slash\). See Section) s
+5 558 M
+( ``File Names'' for more information on file names. This will return) s
+5 547 M
+( an error if the path does not specify a directory or if the directory) s
+5 536 M
+( is not readable. The server will respond to this request with either) s
+5 525 M
+( a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.) s
+5 503 M
+( Once the directory has been successfully opened, files \(and) s
+5 492 M
+( directories\) contained in it can be listed using SSH_FXP_READDIR) s
+5 481 M
+( requests. These are of the format) s
+5 459 M
+( uint32 id) s
+5 448 M
+( string handle) s
+5 426 M
+( where `id' is the request identifier, and `handle' is a handle) s
+5 415 M
+( returned by SSH_FXP_OPENDIR. \(It is a protocol error to attempt to) s
+5 404 M
+( use an ordinary file handle returned by SSH_FXP_OPEN.\)) s
+5 382 M
+( The server responds to this request with either a SSH_FXP_NAME or a) s
+5 371 M
+( SSH_FXP_STATUS message. One or more names may be returned at a time.) s
+5 360 M
+( Full status information is returned for each name in order to speed) s
+5 349 M
+( up typical directory listings.) s
+5 327 M
+( If there are no more names available to be read, the server MUST) s
+5 316 M
+( respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF.) s
+5 294 M
+( When the client no longer wishes to read more names from the) s
+5 283 M
+( directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle) s
+5 272 M
+( should be closed regardless of whether an error has occurred or not.) s
+5 250 M
+(6.8 Retrieving File Attributes) s
+5 228 M
+( Very often, file attributes are automatically returned by) s
+5 217 M
+( SSH_FXP_READDIR. However, sometimes there is need to specifically) s
+5 206 M
+( retrieve the attributes for a named file. This can be done using the) s
+5 195 M
+( SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.) s
+5 173 M
+( SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 20]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (20,21) 11
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 21 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( follows symbolic links on the server, whereas SSH_FXP_LSTAT does not) s
+5 679 M
+( follow symbolic links. Both have the same format:) s
+5 657 M
+( uint32 id) s
+5 646 M
+( string path [UTF-8]) s
+5 635 M
+( uint32 flags) s
+5 613 M
+( where `id' is the request identifier, and `path' specifies the file) s
+5 602 M
+( system object for which status is to be returned. The server) s
+5 591 M
+( responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
+5 569 M
+( The flags field specify the attribute flags in which the client has) s
+5 558 M
+( particular interest. This is a hint to the server. For example,) s
+5 547 M
+( because retrieving owner / group and acl information can be an) s
+5 536 M
+( expensive operation under some operating systems, the server may) s
+5 525 M
+( choose not to retrieve this information unless the client expresses a) s
+5 514 M
+( specific interest in it.) s
+5 492 M
+( The client has no guarantee the server will provide all the fields) s
+5 481 M
+( that it has expressed an interest in.) s
+5 459 M
+( SSH_FXP_FSTAT differs from the others in that it returns status) s
+5 448 M
+( information for an open file \(identified by the file handle\). Its) s
+5 437 M
+( format is as follows:) s
+5 415 M
+( uint32 id) s
+5 404 M
+( string handle) s
+5 393 M
+( uint32 flags) s
+5 371 M
+( where `id' is the request identifier and `handle' is a file handle) s
+5 360 M
+( returned by SSH_FXP_OPEN. The server responds to this request with) s
+5 349 M
+( SSH_FXP_ATTRS or SSH_FXP_STATUS.) s
+5 327 M
+(6.9 Setting File Attributes) s
+5 305 M
+( File attributes may be modified using the SSH_FXP_SETSTAT and) s
+5 294 M
+( SSH_FXP_FSETSTAT requests. These requests are used for operations) s
+5 283 M
+( such as changing the ownership, permissions or access times, as well) s
+5 272 M
+( as for truncating a file.) s
+5 250 M
+( The SSH_FXP_SETSTAT request is of the following format:) s
+5 228 M
+( uint32 id) s
+5 217 M
+( string path [UTF-8]) s
+5 206 M
+( ATTRS attrs) s
+5 184 M
+( where `id' is the request identifier, `path' specifies the file) s
+5 173 M
+( system object \(e.g. file or directory\) whose attributes are to be) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 21]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 22 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( modified, and `attrs' specifies the modifications to be made to its) s
+5 679 M
+( attributes. Attributes are discussed in more detail in Section) s
+5 668 M
+( ``File Attributes''.) s
+5 646 M
+( An error will be returned if the specified file system object does) s
+5 635 M
+( not exist or the user does not have sufficient rights to modify the) s
+5 624 M
+( specified attributes. The server responds to this request with a) s
+5 613 M
+( SSH_FXP_STATUS message.) s
+5 591 M
+( The SSH_FXP_FSETSTAT request modifies the attributes of a file which) s
+5 580 M
+( is already open. It has the following format:) s
+5 558 M
+( uint32 id) s
+5 547 M
+( string handle) s
+5 536 M
+( ATTRS attrs) s
+5 514 M
+( where `id' is the request identifier, `handle' \(MUST be returned by) s
+5 503 M
+( SSH_FXP_OPEN\) identifies the file whose attributes are to be) s
+5 492 M
+( modified, and `attrs' specifies the modifications to be made to its) s
+5 481 M
+( attributes. Attributes are discussed in more detail in Section) s
+5 470 M
+( ``File Attributes''. The server will respond to this request with) s
+5 459 M
+( SSH_FXP_STATUS.) s
+5 437 M
+(6.10 Dealing with Symbolic links) s
+5 415 M
+( The SSH_FXP_READLINK request may be used to read the target of a) s
+5 404 M
+( symbolic link. It would have a data part as follows:) s
+5 382 M
+( uint32 id) s
+5 371 M
+( string path [UTF-8]) s
+5 349 M
+( where `id' is the request identifier and `path' specifies the path) s
+5 338 M
+( name of the symlink to be read.) s
+5 316 M
+( The server will respond with a SSH_FXP_NAME packet containing only) s
+5 305 M
+( one name and a dummy attributes value. The name in the returned) s
+5 294 M
+( packet contains the target of the link. If an error occurs, the) s
+5 283 M
+( server may respond with SSH_FXP_STATUS.) s
+5 261 M
+( The SSH_FXP_SYMLINK request will create a symbolic link on the) s
+5 250 M
+( server. It is of the following format) s
+5 228 M
+( uint32 id) s
+5 217 M
+( string linkpath [UTF-8]) s
+5 206 M
+( string targetpath [UTF-8]) s
+5 184 M
+( where `id' is the request identifier, `linkpath' specifies the path) s
+5 173 M
+( name of the symlink to be created and `targetpath' specifies the) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 22]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (22,23) 12
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 23 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( target of the symlink. The server shall respond with a) s
+5 679 M
+( SSH_FXP_STATUS indicating either success \(SSH_FX_OK\) or an error) s
+5 668 M
+( condition.) s
+5 646 M
+(6.11 Canonicalizing the Server-Side Path Name) s
+5 624 M
+( The SSH_FXP_REALPATH request can be used to have the server) s
+5 613 M
+( canonicalize any given path name to an absolute path. This is useful) s
+5 602 M
+( for converting path names containing ".." components or relative) s
+5 591 M
+( pathnames without a leading slash into absolute paths. The format of) s
+5 580 M
+( the request is as follows:) s
+5 558 M
+( uint32 id) s
+5 547 M
+( string path [UTF-8]) s
+5 525 M
+( where `id' is the request identifier and `path' specifies the path) s
+5 514 M
+( name to be canonicalized. The server will respond with a) s
+5 503 M
+( SSH_FXP_NAME packet containing the name in canonical form and a dummy) s
+5 492 M
+( attributes value. If an error occurs, the server may also respond) s
+5 481 M
+( with SSH_FXP_STATUS.) s
+5 459 M
+(6.11.1 Best practice for dealing with paths) s
+5 437 M
+( The client SHOULD treat the results of SSH_FXP_REALPATH as a) s
+5 426 M
+( canonical absolute path, even if the path does not appear to be) s
+5 415 M
+( absolute. A client that use REALPATH\("."\) and treats the result as) s
+5 404 M
+( absolute, even if there is no leading slash, will continue to) s
+5 393 M
+( function correctly, even when talking to a Windows NT or VMS style) s
+5 382 M
+( system, where absolute paths may not begin with a slash.) s
+5 360 M
+( For example, if the client wishes to change directory up, and the) s
+5 349 M
+( server has returned "c:/x/y/z" from REALPATH, the client SHOULD use) s
+5 338 M
+( "c:/x/y/z/..".) s
+5 316 M
+( As a second example, if the client wishes to open the file "x.txt" in) s
+5 305 M
+( the current directory, and server has returned "dka100:/x/y/z" as the) s
+5 294 M
+( canonical path of the directory, the client SHOULD open "dka100:/x/y/) s
+5 283 M
+( z/x.txt") s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 23]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 24 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(7. Responses from the Server to the Client) s
+5 668 M
+( The server responds to the client using one of a few response) s
+5 657 M
+( packets. All requests can return a SSH_FXP_STATUS response upon) s
+5 646 M
+( failure. When the operation is successful, any of the responses may) s
+5 635 M
+( be returned \(depending on the operation\). If no data needs to be) s
+5 624 M
+( returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK) s
+5 613 M
+( status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used) s
+5 602 M
+( to return a file handle \(for SSH_FXP_OPEN and SSH_FXP_OPENDIR) s
+5 591 M
+( requests\), SSH_FXP_DATA is used to return data from SSH_FXP_READ,) s
+5 580 M
+( SSH_FXP_NAME is used to return one or more file names from a) s
+5 569 M
+( SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is) s
+5 558 M
+( used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and) s
+5 547 M
+( SSH_FXP_FSTAT requests.) s
+5 525 M
+( Exactly one response will be returned for each request. Each) s
+5 514 M
+( response packet contains a request identifier which can be used to) s
+5 503 M
+( match each response with the corresponding request. Note that it is) s
+5 492 M
+( legal to have several requests outstanding simultaneously, and the) s
+5 481 M
+( server is allowed to send responses to them in a different order from) s
+5 470 M
+( the order in which the requests were sent \(the result of their) s
+5 459 M
+( execution, however, is guaranteed to be as if they had been processed) s
+5 448 M
+( one at a time in the order in which the requests were sent\).) s
+5 426 M
+( Response packets are of the same general format as request packets.) s
+5 415 M
+( Each response packet begins with the request identifier.) s
+5 393 M
+( The format of the data portion of the SSH_FXP_STATUS response is as) s
+5 382 M
+( follows:) s
+5 360 M
+( uint32 id) s
+5 349 M
+( uint32 error/status code) s
+5 338 M
+( string error message \(ISO-10646 UTF-8 [RFC-2279]\)) s
+5 327 M
+( string language tag \(as defined in [RFC-1766]\)) s
+5 305 M
+( where `id' is the request identifier, and `error/status code') s
+5 294 M
+( indicates the result of the requested operation. The value SSH_FX_OK) s
+5 283 M
+( indicates success, and all other values indicate failure.) s
+5 261 M
+( Currently, the following values are defined \(other values may be) s
+5 250 M
+( defined by future versions of this protocol\):) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 24]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (24,25) 13
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 25 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( #define SSH_FX_OK 0) s
+5 679 M
+( #define SSH_FX_EOF 1) s
+5 668 M
+( #define SSH_FX_NO_SUCH_FILE 2) s
+5 657 M
+( #define SSH_FX_PERMISSION_DENIED 3) s
+5 646 M
+( #define SSH_FX_FAILURE 4) s
+5 635 M
+( #define SSH_FX_BAD_MESSAGE 5) s
+5 624 M
+( #define SSH_FX_NO_CONNECTION 6) s
+5 613 M
+( #define SSH_FX_CONNECTION_LOST 7) s
+5 602 M
+( #define SSH_FX_OP_UNSUPPORTED 8) s
+5 591 M
+( #define SSH_FX_INVALID_HANDLE 9) s
+5 580 M
+( #define SSH_FX_NO_SUCH_PATH 10) s
+5 569 M
+( #define SSH_FX_FILE_ALREADY_EXISTS 11) s
+5 558 M
+( #define SSH_FX_WRITE_PROTECT 12) s
+5 536 M
+( SSH_FX_OK) s
+5 525 M
+( Indicates successful completion of the operation.) s
+5 503 M
+( SSH_FX_EOF) s
+5 492 M
+( indicates end-of-file condition; for SSH_FX_READ it means that no) s
+5 481 M
+( more data is available in the file, and for SSH_FX_READDIR it) s
+5 470 M
+( indicates that no more files are contained in the directory.) s
+5 448 M
+( SSH_FX_NO_SUCH_FILE) s
+5 437 M
+( is returned when a reference is made to a file which does not) s
+5 426 M
+( exist.) s
+5 404 M
+( SSH_FX_PERMISSION_DENIED) s
+5 393 M
+( is returned when the authenticated user does not have sufficient) s
+5 382 M
+( permissions to perform the operation.) s
+5 360 M
+( SSH_FX_FAILURE) s
+5 349 M
+( is a generic catch-all error message; it should be returned if an) s
+5 338 M
+( error occurs for which there is no more specific error code) s
+5 327 M
+( defined.) s
+5 305 M
+( SSH_FX_BAD_MESSAGE) s
+5 294 M
+( may be returned if a badly formatted packet or protocol) s
+5 283 M
+( incompatibility is detected.) s
+5 261 M
+( SSH_FX_NO_CONNECTION) s
+5 250 M
+( is a pseudo-error which indicates that the client has no) s
+5 239 M
+( connection to the server \(it can only be generated locally by the) s
+5 228 M
+( client, and MUST NOT be returned by servers\).) s
+5 206 M
+( SSH_FX_CONNECTION_LOST) s
+5 195 M
+( is a pseudo-error which indicates that the connection to the) s
+5 184 M
+( server has been lost \(it can only be generated locally by the) s
+5 173 M
+( client, and MUST NOT be returned by servers\).) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 25]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 26 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( SSH_FX_OP_UNSUPPORTED) s
+5 679 M
+( indicates that an attempt was made to perform an operation which) s
+5 668 M
+( is not supported for the server \(it may be generated locally by) s
+5 657 M
+( the client if e.g. the version number exchange indicates that a) s
+5 646 M
+( required feature is not supported by the server, or it may be) s
+5 635 M
+( returned by the server if the server does not implement an) s
+5 624 M
+( operation\).) s
+5 602 M
+( SSH_FX_INVALID_HANDLE) s
+5 591 M
+( The handle value was invalid.) s
+5 569 M
+( SSH_FX_NO_SUCH_PATH) s
+5 558 M
+( The file path does not exist or is invalid.) s
+5 536 M
+( SSH_FX_FILE_ALREADY_EXISTS) s
+5 525 M
+( The file already exists.) s
+5 503 M
+( SSH_FX_WRITE_PROTECT) s
+5 492 M
+( The file is on read only media, or the media is write protected.) s
+5 470 M
+( The SSH_FXP_HANDLE response has the following format:) s
+5 448 M
+( uint32 id) s
+5 437 M
+( string handle) s
+5 415 M
+( where `id' is the request identifier, and `handle' is an arbitrary) s
+5 404 M
+( string that identifies an open file or directory on the server. The) s
+5 393 M
+( handle is opaque to the client; the client MUST NOT attempt to) s
+5 382 M
+( interpret or modify it in any way. The length of the handle string) s
+5 371 M
+( MUST NOT exceed 256 data bytes.) s
+5 349 M
+( The SSH_FXP_DATA response has the following format:) s
+5 327 M
+( uint32 id) s
+5 316 M
+( string data) s
+5 294 M
+( where `id' is the request identifier, and `data' is an arbitrary byte) s
+5 283 M
+( string containing the requested data. The data string may be at most) s
+5 272 M
+( the number of bytes requested in a SSH_FXP_READ request, but may also) s
+5 261 M
+( be shorter if end of file is reached or if the read is from something) s
+5 250 M
+( other than a regular file.) s
+5 228 M
+( The SSH_FXP_NAME response has the following format:) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 26]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (26,27) 14
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 27 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( uint32 id) s
+5 679 M
+( uint32 count) s
+5 668 M
+( repeats count times:) s
+5 657 M
+( string filename [UTF-8]) s
+5 646 M
+( ATTRS attrs) s
+5 624 M
+( where `id' is the request identifier, `count' is the number of names) s
+5 613 M
+( returned in this response, and the remaining fields repeat `count') s
+5 602 M
+( times \(so that all three fields are first included for the first) s
+5 591 M
+( file, then for the second file, etc\). In the repeated part,) s
+5 580 M
+( `filename' is a file name being returned \(for SSH_FXP_READDIR, it) s
+5 569 M
+( will be a relative name within the directory, without any path) s
+5 558 M
+( components; for SSH_FXP_REALPATH it will be an absolute path name\),) s
+5 547 M
+( and `attrs' is the attributes of the file as described in Section) s
+5 536 M
+( ``File Attributes''.) s
+5 514 M
+( The SSH_FXP_ATTRS response has the following format:) s
+5 492 M
+( uint32 id) s
+5 481 M
+( ATTRS attrs) s
+5 459 M
+( where `id' is the request identifier, and `attrs' is the returned) s
+5 448 M
+( file attributes as described in Section ``File Attributes''.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 27]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 28 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(8. Vendor-Specific Extensions) s
+5 668 M
+( The SSH_FXP_EXTENDED request provides a generic extension mechanism) s
+5 657 M
+( for adding vendor-specific commands. The request has the following) s
+5 646 M
+( format:) s
+5 624 M
+( uint32 id) s
+5 613 M
+( string extended-request) s
+5 602 M
+( ... any request-specific data ...) s
+5 580 M
+( where `id' is the request identifier, and `extended-request' is a) s
+5 569 M
+( string of the format "name@domain", where domain is an internet) s
+5 558 M
+( domain name of the vendor defining the request. The rest of the) s
+5 547 M
+( request is completely vendor-specific, and servers should only) s
+5 536 M
+( attempt to interpret it if they recognize the `extended-request') s
+5 525 M
+( name.) s
+5 503 M
+( The server may respond to such requests using any of the response) s
+5 492 M
+( packets defined in Section ``Responses from the Server to the) s
+5 481 M
+( Client''. Additionally, the server may also respond with a) s
+5 470 M
+( SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does) s
+5 459 M
+( not recognize the `extended-request' name, then the server MUST) s
+5 448 M
+( respond with SSH_FXP_STATUS with error/status set to) s
+5 437 M
+( SSH_FX_OP_UNSUPPORTED.) s
+5 415 M
+( The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary) s
+5 404 M
+( extension-specific data from the server to the client. It is of the) s
+5 393 M
+( following format:) s
+5 371 M
+( uint32 id) s
+5 360 M
+( ... any request-specific data ...) s
+5 338 M
+( There is a range of packet types reserved for use by extensions. In) s
+5 327 M
+( order to avoid collision, extensions that turn on the use of) s
+5 316 M
+( additional packet types should determine those numbers dynamically.) s
+5 294 M
+( The suggested way of doing this is have an extension request from the) s
+5 283 M
+( client to the server that enables the extension; the extension) s
+5 272 M
+( response from the server to the client would specify the actual type) s
+5 261 M
+( values to use, in additional to any other data.) s
+5 239 M
+( Extension authors should be mindful of the limited range of packet) s
+5 228 M
+( types available \(there are only 45 values available\) and avoid) s
+5 217 M
+( requiring a new packet type where possible.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 28]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (28,29) 15
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 29 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(9. Security Considerations) s
+5 668 M
+( This protocol assumes that it is run over a secure channel and that) s
+5 657 M
+( the endpoints of the channel have been authenticated. Thus, this) s
+5 646 M
+( protocol assumes that it is externally protected from network-level) s
+5 635 M
+( attacks.) s
+5 613 M
+( This protocol provides file system access to arbitrary files on the) s
+5 602 M
+( server \(only constrained by the server implementation\). It is the) s
+5 591 M
+( responsibility of the server implementation to enforce any access) s
+5 580 M
+( controls that may be required to limit the access allowed for any) s
+5 569 M
+( particular user \(the user being authenticated externally to this) s
+5 558 M
+( protocol, typically using the SSH User Authentication Protocol [8].) s
+5 536 M
+( Care must be taken in the server implementation to check the validity) s
+5 525 M
+( of received file handle strings. The server should not rely on them) s
+5 514 M
+( directly; it MUST check the validity of each handle before relying on) s
+5 503 M
+( it.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 29]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 30 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(10. Changes from previous protocol versions) s
+5 668 M
+( The SSH File Transfer Protocol has changed over time, before it's) s
+5 657 M
+( standardization. The following is a description of the incompatible) s
+5 646 M
+( changes between different versions.) s
+5 624 M
+(10.1 Changes between versions 4 and 3) s
+5 602 M
+( Many of the changes between version 4 and version 3 are to the) s
+5 591 M
+( attribute structure to make it more flexible for non-unix platforms.) s
+5 569 M
+( o Make all filenames UTF-8.) s
+5 547 M
+( o Added 'newline' extension.) s
+5 525 M
+( o Made file attribute owner and group strings so they can actually) s
+5 514 M
+( be used on disparate systems.) s
+5 492 M
+( o Added createtime field, and added separate flags for atime,) s
+5 481 M
+( createtime, and mtime so they can be set separately.) s
+5 459 M
+( o Split the file type out of the permissions field and into it's own) s
+5 448 M
+( field \(which is always present.\)) s
+5 426 M
+( o Added acl attribute.) s
+5 404 M
+( o Added SSH_FXF_TEXT file open flag.) s
+5 382 M
+( o Added flags field to the get stat commands so that the client can) s
+5 371 M
+( specifically request information the server might not normally) s
+5 360 M
+( included for performance reasons.) s
+5 338 M
+( o Removed the long filename from the names structure-- it can now be) s
+5 327 M
+( built from information available in the attrs structure.) s
+5 305 M
+( o Added reserved range of packet numbers for extensions.) s
+5 283 M
+( o Added several additional error codes.) s
+5 261 M
+( o Change the way version negotiate works slightly. Previously, if) s
+5 250 M
+( the client version were higher than the server version, the server) s
+5 239 M
+( was supposed to 'echo back' the clients version. The server now) s
+5 228 M
+( sends it's own version and the lower of the two is considered to) s
+5 217 M
+( be the one in use.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 30]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (30,31) 16
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 31 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(10.2 Changes between versions 3 and 2) s
+5 668 M
+( o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.) s
+5 646 M
+( o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were) s
+5 635 M
+( added.) s
+5 613 M
+( o The SSH_FXP_STATUS message was changed to include fields `error) s
+5 602 M
+( message' and `language tag'.) s
+5 569 M
+(10.3 Changes between versions 2 and 1) s
+5 547 M
+( o The SSH_FXP_RENAME message was added.) s
+5 514 M
+(10.4 Changes between versions 1 and 0) s
+5 492 M
+( o Implementation changes, no actual protocol changes.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 31]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 32 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(11. Trademark Issues) s
+5 668 M
+( "ssh" is a registered trademark of SSH Communications Security Corp) s
+5 657 M
+( in the United States and/or other countries.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 32]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (32,33) 17
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 33 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(References) s
+5 668 M
+( [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and) s
+5 657 M
+( P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January) s
+5 646 M
+( 1999.) s
+5 624 M
+( [2] Alvestrand, H., "IETF Policy on Character Sets and Languages",) s
+5 613 M
+( BCP 18, RFC 2277, January 1998.) s
+5 591 M
+( [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,) s
+5 580 M
+( C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC) s
+5 569 M
+( 3010, December 2000.) s
+5 547 M
+( [4] Institute of Electrical and Electronics Engineers, "Information) s
+5 536 M
+( Technology - Portable Operating System Interface \(POSIX\) - Part) s
+5 525 M
+( 1: System Application Program Interface \(API\) [C Language]",) s
+5 514 M
+( IEEE Standard 1003.2, 1996.) s
+5 492 M
+( [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 481 M
+( Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-) s
+5 470 M
+( architecture-13 \(work in progress\), September 2002.) s
+5 448 M
+( [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 437 M
+( Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-) s
+5 426 M
+( transport-15 \(work in progress\), September 2002.) s
+5 404 M
+( [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 393 M
+( Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16) s
+5 382 M
+( \(work in progress\), September 2002.) s
+5 360 M
+( [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.) s
+5 349 M
+( Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-) s
+5 338 M
+( userauth-16 \(work in progress\), September 2002.) s
+5 305 M
+(Authors' Addresses) s
+5 283 M
+( Joseph Galbraith) s
+5 272 M
+( VanDyke Software) s
+5 261 M
+( 4848 Tramway Ridge Blvd) s
+5 250 M
+( Suite 101) s
+5 239 M
+( Albuquerque, NM 87111) s
+5 228 M
+( US) s
+5 206 M
+( Phone: +1 505 332 5700) s
+5 195 M
+( EMail: [email protected]) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 33]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 34 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+( Tatu Ylonen) s
+5 679 M
+( SSH Communications Security Corp) s
+5 668 M
+( Fredrikinkatu 42) s
+5 657 M
+( HELSINKI FIN-00100) s
+5 646 M
+( Finland) s
+5 624 M
+( EMail: [email protected]) s
+5 591 M
+( Sami Lehtinen) s
+5 580 M
+( SSH Communications Security Corp) s
+5 569 M
+( Fredrikinkatu 42) s
+5 558 M
+( HELSINKI FIN-00100) s
+5 547 M
+( Finland) s
+5 525 M
+( EMail: [email protected]) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 34]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (34,35) 18
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 35 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH File Transfer Protocol October 2002) s
+5 690 M
+(Full Copyright Statement) s
+5 668 M
+( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
+5 646 M
+( This document and translations of it may be copied and furnished to) s
+5 635 M
+( others, and derivative works that comment on or otherwise explain it) s
+5 624 M
+( or assist in its implementation may be prepared, copied, published) s
+5 613 M
+( and distributed, in whole or in part, without restriction of any) s
+5 602 M
+( kind, provided that the above copyright notice and this paragraph are) s
+5 591 M
+( included on all such copies and derivative works. However, this) s
+5 580 M
+( document itself may not be modified in any way, such as by removing) s
+5 569 M
+( the copyright notice or references to the Internet Society or other) s
+5 558 M
+( Internet organizations, except as needed for the purpose of) s
+5 547 M
+( developing Internet standards in which case the procedures for) s
+5 536 M
+( copyrights defined in the Internet Standards process must be) s
+5 525 M
+( followed, or as required to translate it into languages other than) s
+5 514 M
+( English.) s
+5 492 M
+( The limited permissions granted above are perpetual and will not be) s
+5 481 M
+( revoked by the Internet Society or its successors or assigns.) s
+5 459 M
+( This document and the information contained herein is provided on an) s
+5 448 M
+( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
+5 437 M
+( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
+5 426 M
+( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
+5 415 M
+( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
+5 404 M
+( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
+5 382 M
+(Acknowledgement) s
+5 360 M
+( Funding for the RFC Editor function is currently provided by the) s
+5 349 M
+( Internet Society.) s
+5 129 M
+(Galbraith, et al. Expires April 16, 2003 [Page 35]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 36 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+_R
+S
+PStoPSsaved restore
+%%Trailer
+%%Pages: 36
+%%DocumentNeededResources: font Courier-Bold Courier
+%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt
new file mode 100644
index 0000000000..83960ae976
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-03.txt
@@ -0,0 +1,1962 @@
+
+
+
+Secure Shell Working Group J. Galbraith
+Internet-Draft VanDyke Software
+Expires: April 16, 2003 T. Ylonen
+ S. Lehtinen
+ SSH Communications Security Corp
+ October 16, 2002
+
+
+ SSH File Transfer Protocol
+ draft-ietf-secsh-filexfer-03.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on April 16, 2003.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ The SSH File Transfer Protocol provides secure file transfer
+ functionality over any reliable data stream. It is the standard file
+ transfer protocol for use with the SSH2 protocol. This document
+ describes the file transfer protocol and its interface to the SSH2
+ protocol suite.
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 1]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4
+ 3. General Packet Format . . . . . . . . . . . . . . . . . . 5
+ 4. Protocol Initialization . . . . . . . . . . . . . . . . . 7
+ 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 7
+ 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 7
+ 4.3 Determining Server Newline Convention . . . . . . . . . . 8
+ 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 9
+ 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 10
+ 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 11
+ 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 12
+ 6. Requests From the Client to the Server . . . . . . . . . . 13
+ 6.1 Request Synchronization and Reordering . . . . . . . . . . 13
+ 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 14
+ 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 14
+ 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 17
+ 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 18
+ 6.6 Creating and Deleting Directories . . . . . . . . . . . . 19
+ 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 19
+ 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 20
+ 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 21
+ 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 22
+ 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 23
+ 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 23
+ 7. Responses from the Server to the Client . . . . . . . . . 24
+ 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 28
+ 9. Security Considerations . . . . . . . . . . . . . . . . . 29
+ 10. Changes from previous protocol versions . . . . . . . . . 30
+ 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 30
+ 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 31
+ 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 31
+ 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 31
+ 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 32
+ References . . . . . . . . . . . . . . . . . . . . . . . . 33
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . 33
+ Full Copyright Statement . . . . . . . . . . . . . . . . . 35
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 2]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+1. Introduction
+
+ This protocol provides secure file transfer (and more generally file
+ system access) functionality over a reliable data stream, such as a
+ channel in the SSH2 protocol [5].
+
+ This protocol is designed so that it could be used to implement a
+ secure remote file system service, as well as a secure file transfer
+ service.
+
+ This protocol assumes that it runs over a secure channel, and that
+ the server has already authenticated the user at the client end, and
+ that the identity of the client user is externally available to the
+ server implementation.
+
+ In general, this protocol follows a simple request-response model.
+ Each request and response contains a sequence number and multiple
+ requests may be pending simultaneously. There are a relatively large
+ number of different request messages, but a small number of possible
+ response messages. Each request has one or more response messages
+ that may be returned in result (e.g., a read either returns data or
+ reports error status).
+
+ The packet format descriptions in this specification follow the
+ notation presented in the secsh architecture draft. [5]
+
+ Even though this protocol is described in the context of the SSH2
+ protocol, this protocol is general and independent of the rest of the
+ SSH2 protocol suite. It could be used in a number of different
+ applications, such as secure file transfer over TLS RFC 2246 [1] and
+ transfer of management information in VPN applications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 3]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+2. Use with the SSH Connection Protocol
+
+ When used with the SSH2 Protocol suite, this protocol is intended to
+ be used from the SSH Connection Protocol [7] as a subsystem, as
+ described in section ``Starting a Shell or a Command''. The
+ subsystem name used with this protocol is "sftp".
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 4]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+3. General Packet Format
+
+ All packets transmitted over the secure connection are of the
+ following format:
+
+ uint32 length
+ byte type
+ byte[length - 1] data payload
+
+ That is, they are just data preceded by 32-bit length and 8-bit type
+ fields. The `length' is the length of the data area, and does not
+ include the `length' field itself. The format and interpretation of
+ the data area depends on the packet type.
+
+ All packet descriptions below only specify the packet type and the
+ data that goes into the data field. Thus, they should be prefixed by
+ the `length' and `type' fields.
+
+ The maximum size of a packet is in practice determined by the client
+ (the maximum size of read or write requests that it sends, plus a few
+ bytes of packet overhead). All servers SHOULD support packets of at
+ least 34000 bytes (where the packet size refers to the full length,
+ including the header above). This should allow for reads and writes
+ of at most 32768 bytes.
+
+ There is no limit on the number of outstanding (non-acknowledged)
+ requests that the client may send to the server. In practice this is
+ limited by the buffering available on the data stream and the queuing
+ performed by the server. If the server's queues are full, it should
+ not read any more data from the stream, and flow control will prevent
+ the client from sending more requests. Note, however, that while
+ there is no restriction on the protocol level, the client's API may
+ provide a limit in order to prevent infinite queuing of outgoing
+ requests at the client.
+
+ The following values are defined for packet types.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 5]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ #define SSH_FXP_INIT 1
+ #define SSH_FXP_VERSION 2
+ #define SSH_FXP_OPEN 3
+ #define SSH_FXP_CLOSE 4
+ #define SSH_FXP_READ 5
+ #define SSH_FXP_WRITE 6
+ #define SSH_FXP_LSTAT 7
+ #define SSH_FXP_FSTAT 8
+ #define SSH_FXP_SETSTAT 9
+ #define SSH_FXP_FSETSTAT 10
+ #define SSH_FXP_OPENDIR 11
+ #define SSH_FXP_READDIR 12
+ #define SSH_FXP_REMOVE 13
+ #define SSH_FXP_MKDIR 14
+ #define SSH_FXP_RMDIR 15
+ #define SSH_FXP_REALPATH 16
+ #define SSH_FXP_STAT 17
+ #define SSH_FXP_RENAME 18
+ #define SSH_FXP_READLINK 19
+ #define SSH_FXP_SYMLINK 20
+
+ #define SSH_FXP_STATUS 101
+ #define SSH_FXP_HANDLE 102
+ #define SSH_FXP_DATA 103
+ #define SSH_FXP_NAME 104
+ #define SSH_FXP_ATTRS 105
+
+ #define SSH_FXP_EXTENDED 200
+ #define SSH_FXP_EXTENDED_REPLY 201
+
+ RESERVED_FOR_EXTENSIONS 210-255
+
+ Additional packet types should only be defined if the protocol
+ version number (see Section ``Protocol Initialization'') is
+ incremented, and their use MUST be negotiated using the version
+ number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY
+ packets can be used to implement vendor-specific extensions. See
+ Section ``Vendor-Specific-Extensions'' for more details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 6]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+4. Protocol Initialization
+
+ When the file transfer protocol starts, the client first sends a
+ SSH_FXP_INIT (including its version number) packet to the server.
+ The server responds with a SSH_FXP_VERSION packet, supplying the
+ lowest of its own and the client's version number. Both parties
+ should from then on adhere to particular version of the protocol.
+
+ The version number of the protocol specified in this document is 4.
+ The version number should be incremented for each incompatible
+ revision of this protocol.
+
+4.1 Client Initialization
+
+ The SSH_FXP_INIT packet (from client to server) has the following
+ data:
+
+ uint32 version
+
+ Version 3 of this protocol allowed clients to include extensions in
+ the SSH_FXP_INIT packet; however, this can cause interoperability
+ problems with version 1 and version 2 servers because the client must
+ send this packet before knowing the servers version.
+
+ In this version of the protocol, clients MUST use the
+ SSH_FXP_EXTENDED packet to send extensions to the server after
+ version exchange has completed. Clients MUST NOT include extensions
+ in the version packet. This will prevent interoperability problems
+ with older servers
+
+4.2 Server Initialization
+
+ The SSH_FXP_VERSION packet (from server to client) has the following
+ data:
+
+ uint32 version
+ <extension data>
+
+ 'version' is the lower of the protocol version supported by the
+ server and the version number received from the client.
+
+ The extension data may be empty, or may be a sequence of
+
+ string extension_name
+ string extension_data
+
+ pairs (both strings MUST always be present if one is, but the
+ `extension_data' string may be of zero length). If present, these
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 7]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ strings indicate extensions to the baseline protocol. The
+ `extension_name' field(s) identify the name of the extension. The
+ name should be of the form "name@domain", where the domain is the DNS
+ domain name of the organization defining the extension. Additional
+ names that are not of this format may be defined later by the IETF.
+ Implementations MUST silently ignore any extensions whose name they
+ do not recognize.
+
+4.3 Determining Server Newline Convention
+
+ In order to correctly process text files in a cross platform
+ compatible way, the newline convention must be converted from that of
+ the server to that of the client, or, during an upload, from that of
+ the client to that of the server.
+
+ Versions 3 and prior of this protocol made no provisions for
+ processing text files. Many clients implemented some sort of
+ conversion algorithm, but without either a 'canonical' on the wire
+ format or knowledge of the servers newline convention, correct
+ conversion was not always possible.
+
+ Starting with Version 4, the SSH_FXF_TEXT file open flag (Section
+ 6.3) makes it possible to request that the server translate a file to
+ a 'canonical' on the wire format. This format uses \r\n as the line
+ separator.
+
+ Servers for systems using multiple newline characters (for example,
+ Mac OS X or VMS) or systems using counted records, MUST translate to
+ the canonical form.
+
+ However, to ease the burden of implementation on servers that use a
+ single, simple separator sequence, the following extension allows the
+ canonical format to be changed.
+
+ string "newline"
+ string new-canonical-separator (usually "\r" or "\n" or "\r\n")
+
+ All clients MUST support this extension.
+
+ When processing text files, clients SHOULD NOT translate any
+ character or sequence that is not an exact match of the servers
+ newline separator.
+
+ In particular, if the newline sequence being used is the canonical
+ "\r\n" sequence, a lone \r or a lone \n SHOULD be written through
+ without change.
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 8]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+5. File Attributes
+
+ A new compound data type is defined for encoding file attributes.
+ The same encoding is used both when returning file attributes from
+ the server and when sending file attributes to the server. When
+ sending it to the server, the flags field specifies which attributes
+ are included, and the server will use default values for the
+ remaining attributes (or will not modify the values of remaining
+ attributes). When receiving attributes from the server, the flags
+ specify which attributes are included in the returned data. The
+ server normally returns all attributes it knows about.
+
+ uint32 flags
+ byte type always present
+ uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE
+ string owner present only if flag SSH_FILEXFER_ATTR_OWNERGROUP
+ string group present only if flag SSH_FILEXFER_ATTR_OWNERGROUP
+ uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS
+ uint32 atime present only if flag SSH_FILEXFER_ATTR_ACCESSTIME
+ uint32 createtime present only if flag SSH_FILEXFER_ATTR_CREATETIME
+ uint32 mtime present only if flag SSH_FILEXFER_ATTR_MODIFYTIME
+ string acl present only if flag SSH_FILEXFER_ATTR_ACL
+ uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED
+ string extended_type
+ string extended_data
+ ... more extended data (extended_type - extended_data pairs),
+ so that number of pairs equals extended_count
+
+
+5.1 Flags
+
+ The `flags' specify which of the fields are present. Those fields
+ for which the corresponding flag is not set are not present (not
+ included in the packet). New flags can only be added by incrementing
+ the protocol version number (or by using the extension mechanism
+ described below).
+
+ The flags bits are defined to have the following values:
+
+ #define SSH_FILEXFER_ATTR_SIZE 0x00000001
+ #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
+ #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
+ #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
+ #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
+ #define SSH_FILEXFER_ATTR_ACL 0x00000040
+ #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
+ #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 9]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ In previous versions of this protocol flags value 0x00000002 was
+ SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP
+ was given a new value in order to ease implementation burden.
+ 0x00000002 MUST NOT appear in the mask. Some future version of this
+ protocol may reuse flag 0x00000002.
+
+5.2 Type
+
+ The type field is always present. The following types are defined:
+
+ #define SSH_FILEXFER_TYPE_REGULAR 1
+ #define SSH_FILEXFER_TYPE_DIRECTORY 2
+ #define SSH_FILEXFER_TYPE_SYMLINK 3
+ #define SSH_FILEXFER_TYPE_SPECIAL 4
+ #define SSH_FILEXFER_TYPE_UNKNOWN 5
+
+ On a POSIX system, these values would be derived from the permission
+ field.
+
+5.3 Size
+
+ The `size' field specifies the size of the file on disk, in bytes.
+ If it is present during file creation, it should be considered a hint
+ as to the files eventual size.
+
+ Files opened with the SSH_FXF_TEXT flag may have a size that is
+ greater or less than the value of the size field.
+
+5.4 Owner and Group
+
+ The `owner' and `group' fields are represented as UTF-8 strings; this
+ is the form used by NFS v4. See NFS version 4 Protocol. [3] The
+ following text is selected quotations from section 5.6.
+
+ To avoid a representation that is tied to a particular underlying
+ implementation at the client or server, the use of UTF-8 strings has
+ been chosen. The string should be of the form user@dns_domain".
+ This will allow for a client and server that do not use the same
+ local representation the ability to translate to a common syntax that
+ can be interpreted by both. In the case where there is no
+ translation available to the client or server, the attribute value
+ must be constructed without the "@". Therefore, the absence of the @
+ from the owner or owner_group attribute signifies that no translation
+ was available and the receiver of the attribute should not place any
+ special meaning with the attribute value. Even though the attribute
+ value can not be translated, it may still be useful. In the case of
+ a client, the attribute string may be used for local display of
+ ownership.
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 10]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+5.5 Permissions
+
+ The `permissions' field contains a bit mask of file permissions as
+ defined by POSIX [1].
+
+5.6 Times
+
+ The 'atime', 'createtime', and 'mtime' contain the access, creation,
+ and modification times of the files, respectively. They are
+ represented as seconds from Jan 1, 1970 in UTC.
+
+5.7 ACL
+
+ The 'ACL' field contains an ACL similar to that defined in section
+ 5.9 of NFS version 4 Protocol [3].
+
+ uint32 ace-count
+
+ repeated ace-count time:
+ uint32 ace-type
+ uint32 ace-flag
+ uint32 ace-mask
+ string who [UTF-8]
+
+ ace-type is one of the following four values (taken from NFS Version
+ 4 Protocol [3]:
+
+ const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;
+ const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;
+ const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;
+ const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;
+
+ ace-flag is a combination of the following flag values. See NFS
+ Version 4 Protocol [3] section 5.9.2:
+
+ const ACE4_FILE_INHERIT_ACE = 0x00000001;
+ const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;
+ const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;
+ const ACE4_INHERIT_ONLY_ACE = 0x00000008;
+ const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;
+ const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;
+ const ACE4_IDENTIFIER_GROUP = 0x00000040;
+
+ ace-mask is any combination of the following flags (taken from NFS
+ Version 4 Protocol [3] section 5.9.3:
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 11]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ const ACE4_READ_DATA = 0x00000001;
+ const ACE4_LIST_DIRECTORY = 0x00000001;
+ const ACE4_WRITE_DATA = 0x00000002;
+ const ACE4_ADD_FILE = 0x00000002;
+ const ACE4_APPEND_DATA = 0x00000004;
+ const ACE4_ADD_SUBDIRECTORY = 0x00000004;
+ const ACE4_READ_NAMED_ATTRS = 0x00000008;
+ const ACE4_WRITE_NAMED_ATTRS = 0x00000010;
+ const ACE4_EXECUTE = 0x00000020;
+ const ACE4_DELETE_CHILD = 0x00000040;
+ const ACE4_READ_ATTRIBUTES = 0x00000080;
+ const ACE4_WRITE_ATTRIBUTES = 0x00000100;
+ const ACE4_DELETE = 0x00010000;
+ const ACE4_READ_ACL = 0x00020000;
+ const ACE4_WRITE_ACL = 0x00040000;
+ const ACE4_WRITE_OWNER = 0x00080000;
+ const ACE4_SYNCHRONIZE = 0x00100000;
+
+ who is a UTF-8 string of the form described in 'Owner and Group'
+ (Section 5.4)
+
+5.8 Extended attributes
+
+ The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension
+ mechanism for vendor-specific extensions. If the flag is specified,
+ then the `extended_count' field is present. It specifies the number
+ of extended_type-extended_data pairs that follow. Each of these
+ pairs specifies an extended attribute. For each of the attributes,
+ the extended_type field should be a string of the format
+ "name@domain", where "domain" is a valid, registered domain name and
+ "name" identifies the method. The IETF may later standardize certain
+ names that deviate from this format (e.g., that do not contain the
+ "@" sign). The interpretation of `extended_data' depends on the
+ type. Implementations SHOULD ignore extended data fields that they
+ do not understand.
+
+ Additional fields can be added to the attributes by either defining
+ additional bits to the flags field to indicate their presence, or by
+ defining extended attributes for them. The extended attributes
+ mechanism is recommended for most purposes; additional flags bits
+ should only be defined by an IETF standards action that also
+ increments the protocol version number. The use of such new fields
+ MUST be negotiated by the version number in the protocol exchange.
+ It is a protocol error if a packet with unsupported protocol bits is
+ received.
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 12]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+6. Requests From the Client to the Server
+
+ Requests from the client to the server represent the various file
+ system operations. Each request begins with an `id' field, which is
+ a 32-bit identifier identifying the request (selected by the client).
+ The same identifier will be returned in the response to the request.
+ One possible implementation is a monotonically increasing request
+ sequence number (modulo 2^32).
+
+ Many operations in the protocol operate on open files. The
+ SSH_FXP_OPEN request can return a file handle (which is an opaque
+ variable-length string) which may be used to access the file later
+ (e.g. in a read operation). The client MUST NOT send requests the
+ server with bogus or closed handles. However, the server MUST
+ perform adequate checks on the handle in order to avoid security
+ risks due to fabricated handles.
+
+ This design allows either stateful and stateless server
+ implementation, as well as an implementation which caches state
+ between requests but may also flush it. The contents of the file
+ handle string are entirely up to the server and its design. The
+ client should not modify or attempt to interpret the file handle
+ strings.
+
+ The file handle strings MUST NOT be longer than 256 bytes.
+
+6.1 Request Synchronization and Reordering
+
+ The protocol and implementations MUST process requests relating to
+ the same file in the order in which they are received. In other
+ words, if an application submits multiple requests to the server, the
+ results in the responses will be the same as if it had sent the
+ requests one at a time and waited for the response in each case. For
+ example, the server may process non-overlapping read/write requests
+ to the same file in parallel, but overlapping reads and writes cannot
+ be reordered or parallelized. However, there are no ordering
+ restrictions on the server for processing requests from two different
+ file transfer connections. The server may interleave and parallelize
+ them at will.
+
+ There are no restrictions on the order in which responses to
+ outstanding requests are delivered to the client, except that the
+ server must ensure fairness in the sense that processing of no
+ request will be indefinitely delayed even if the client is sending
+ other requests so that there are multiple outstanding requests all
+ the time.
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 13]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+6.2 File Names
+
+ This protocol represents file names as strings. File names are
+ assumed to use the slash ('/') character as a directory separator.
+
+ File names starting with a slash are "absolute", and are relative to
+ the root of the file system. Names starting with any other character
+ are relative to the user's default directory (home directory). Note
+ that identifying the user is assumed to take place outside of this
+ protocol.
+
+ Servers SHOULD interpret a path name component ".." as referring to
+ the parent directory, and "." as referring to the current directory.
+ If the server implementation limits access to certain parts of the
+ file system, it must be extra careful in parsing file names when
+ enforcing such restrictions. There have been numerous reported
+ security bugs where a ".." in a path name has allowed access outside
+ the intended area.
+
+ An empty path name is valid, and it refers to the user's default
+ directory (usually the user's home directory).
+
+ Otherwise, no syntax is defined for file names by this specification.
+ Clients should not make any other assumptions; however, they can
+ splice path name components returned by SSH_FXP_READDIR together
+ using a slash ('/') as the separator, and that will work as expected.
+
+ In order to comply with IETF Policy on Character Sets and Languages
+ [2], all filenames are to be encoded in UTF-8. The shortest valid
+ UTF-8 encoding of the UNICODE data MUST be used. The server is
+ responsible for converting the UNICODE data to whatever canonical
+ form it requires.
+
+ For example, if the server requires that precomposed characters
+ always be used, the server MUST NOT assume the filename as sent by
+ the client has this attribute, but must do this normalization itself.
+
+ It is understood that the lack of well-defined semantics for file
+ names may cause interoperability problems between clients and servers
+ using radically different operating systems. However, this approach
+ is known to work acceptably with most systems, and alternative
+ approaches that e.g. treat file names as sequences of structured
+ components are quite complicated.
+
+6.3 Opening, Creating, and Closing Files
+
+ Files are opened and created using the SSH_FXP_OPEN message, whose
+ data part is as follows:
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 14]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ uint32 id
+ string filename [UTF-8]
+ uint32 pflags
+ ATTRS attrs
+
+ The `id' field is the request identifier as for all requests.
+
+ The `filename' field specifies the file name. See Section ``File
+ Names'' for more information.
+
+ The `pflags' field is a bitmask. The following bits have been
+ defined.
+
+ #define SSH_FXF_READ 0x00000001
+ #define SSH_FXF_WRITE 0x00000002
+ #define SSH_FXF_APPEND 0x00000004
+ #define SSH_FXF_CREAT 0x00000008
+ #define SSH_FXF_TRUNC 0x00000010
+ #define SSH_FXF_EXCL 0x00000020
+ #define SSH_FXF_TEXT 0x00000040
+
+ These have the following meanings:
+
+ SSH_FXF_READ
+ Open the file for reading.
+
+ SSH_FXF_WRITE
+ Open the file for writing. If both this and SSH_FXF_READ are
+ specified, the file is opened for both reading and writing.
+
+ SSH_FXF_APPEND
+ Force all writes to append data at the end of the file. The
+ offset parameter to write will be ignored.
+
+ SSH_FXF_CREAT
+ If this flag is specified, then a new file will be created if one
+ does not already exist (if O_TRUNC is specified, the new file will
+ be truncated to zero length if it previously exists).
+
+ SSH_FXF_TRUNC
+ Forces an existing file with the same name to be truncated to zero
+ length when creating a file by specifying SSH_FXF_CREAT.
+ SSH_FXF_CREAT MUST also be specified if this flag is used.
+
+ SSH_FXF_EXCL
+ Causes the request to fail if the named file already exists.
+ SSH_FXF_CREAT MUST also be specified if this flag is used.
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 15]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ SSH_FXF_TEXT
+ Indicates that the server should treat the file as text and
+ convert it to the canonical newline convention in use. (See
+ Determining Server Newline Convention. (Section 4.3)
+
+ When a file is opened with the FXF_TEXT flag, the offset field in
+ both the read and write function are ignored.
+
+ Servers MUST correctly process multiple parallel reads and writes
+ correctly in this mode. Naturally, it is permissible for them to
+ do this by serializing the requests. It would not be possible for
+ a client to reliably detect a server that does not implement
+ parallel writes in time to prevent damage.
+
+ Clients SHOULD use the SSH_FXF_APPEND flag to append data to a
+ text file rather then using write with a calculated offset.
+
+ To support seeks on text file the following SSH_FXP_EXTENDED
+ packet is defined.
+
+
+
+ string "text-seek"
+ string file-handle
+ uint64 line-number
+
+ line-number is the index of the line number to seek to, where byte
+ 0 in the file is line number 0, and the byte directly following
+ the first newline sequence in the file is line number 1 and so on.
+
+ The response to a "text-seek" request is an SSH_FXP_STATUS
+ message.
+
+ An attempt to seek past the end-of-file should result in a
+ SSH_FX_EOF status.
+
+ Servers SHOULD support at least one "text-seek" in order to
+ support resume. However, a client MUST be prepared to receive
+ SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation.
+ The client can then try a fall-back strategy, if it has one.
+
+ Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned
+ for read or write operations that are not sequential.
+
+ The `attrs' field specifies the initial attributes for the file.
+ Default values will be used for those attributes that are not
+ specified. See Section ``File Attributes'' for more information.
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 16]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ The response to this message will be either SSH_FXP_HANDLE (if the
+ operation is successful) or SSH_FXP_STATUS (if the operation fails).
+
+ A file is closed by using the SSH_FXP_CLOSE request. Its data field
+ has the following format:
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is a handle
+ previously returned in the response to SSH_FXP_OPEN or
+ SSH_FXP_OPENDIR. The handle becomes invalid immediately after this
+ request has been sent.
+
+ The response to this request will be a SSH_FXP_STATUS message. One
+ should note that on some server platforms even a close can fail.
+ This can happen e.g. if the server operating system caches writes,
+ and an error occurs while flushing cached writes during the close.
+
+6.4 Reading and Writing
+
+ Once a file has been opened, it can be read using the SSH_FXP_READ
+ message, which has the following format:
+
+ uint32 id
+ string handle
+ uint64 offset
+ uint32 len
+
+ where `id' is the request identifier, `handle' is an open file handle
+ returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative
+ to the beginning of the file from where to start reading, and `len'
+ is the maximum number of bytes to read.
+
+ In response to this request, the server will read as many bytes as it
+ can from the file (up to `len'), and return them in a SSH_FXP_DATA
+ message. If an error occurs or EOF is encountered before reading any
+ data, the server will respond with SSH_FXP_STATUS. For normal disk
+ files, it is guaranteed that this will read the specified number of
+ bytes, or up to end of file. For e.g. device files this may return
+ fewer bytes than requested.
+
+ Writing to a file is achieved using the SSH_FXP_WRITE message, which
+ has the following format:
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 17]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ uint32 id
+ string handle
+ uint64 offset
+ string data
+
+ where `id' is a request identifier, `handle' is a file handle
+ returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the
+ beginning of the file where to start writing, and `data' is the data
+ to be written.
+
+ The write will extend the file if writing beyond the end of the file.
+ It is legal to write way beyond the end of the file; the semantics
+ are to write zeroes from the end of the file to the specified offset
+ and then the data. On most operating systems, such writes do not
+ allocate disk space but instead leave "holes" in the file.
+
+ The server responds to a write request with a SSH_FXP_STATUS message.
+
+6.5 Removing and Renaming Files
+
+ Files can be removed using the SSH_FXP_REMOVE message. It has the
+ following format:
+
+ uint32 id
+ string filename [UTF-8]
+
+ where `id' is the request identifier and `filename' is the name of
+ the file to be removed. See Section ``File Names'' for more
+ information. This request cannot be used to remove directories.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+ message.
+
+ Files (and directories) can be renamed using the SSH_FXP_RENAME
+ message. Its data is as follows:
+
+ uint32 id
+ string oldpath [UTF-8]
+ string newpath [UTF-8]
+
+ where `id' is the request identifier, `oldpath' is the name of an
+ existing file or directory, and `newpath' is the new name for the
+ file or directory. It is an error if there already exists a file
+ with the name specified by newpath. The server may also fail rename
+ requests in other situations, for example if `oldpath' and `newpath'
+ point to different file systems on the server.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 18]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ message.
+
+6.6 Creating and Deleting Directories
+
+ New directories can be created using the SSH_FXP_MKDIR request. It
+ has the following format:
+
+ uint32 id
+ string path [UTF-8]
+ ATTRS attrs
+
+ where `id' is the request identifier.
+
+ `path' specifies the directory to be created. See Section ``File
+ Names'' for more information on file names.
+
+ `attrs' specifies the attributes that should be applied to it upon
+ creation. Attributes are discussed in more detail in Section ``File
+ Attributes''.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+ message. If a file or directory with the specified path already
+ exists, an error will be returned.
+
+ Directories can be removed using the SSH_FXP_RMDIR request, which has
+ the following format:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier, and `path' specifies the
+ directory to be removed. See Section ``File Names'' for more
+ information on file names.
+
+ The server responds to this request with a SSH_FXP_STATUS message.
+ Errors may be returned from this operation for various reasons,
+ including, but not limited to, the path does not exist, the path does
+ not refer to a directory object, the directory is not empty, or the
+ user has insufficient access or permission to perform the requested
+ operation.
+
+6.7 Scanning Directories
+
+ The files in a directory can be listed using the SSH_FXP_OPENDIR and
+ SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one
+ or more file names with full file attributes for each file. The
+ client should call SSH_FXP_READDIR repeatedly until it has found the
+ file it is looking for or until the server responds with a
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 19]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if
+ there are no more files in the directory). The client should then
+ close the handle using the SSH_FXP_CLOSE request.
+
+ The SSH_FXP_OPENDIR opens a directory for reading. It has the
+ following format:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier and `path' is the path name of
+ the directory to be listed (without any trailing slash). See Section
+ ``File Names'' for more information on file names. This will return
+ an error if the path does not specify a directory or if the directory
+ is not readable. The server will respond to this request with either
+ a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.
+
+ Once the directory has been successfully opened, files (and
+ directories) contained in it can be listed using SSH_FXP_READDIR
+ requests. These are of the format
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is a handle
+ returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to
+ use an ordinary file handle returned by SSH_FXP_OPEN.)
+
+ The server responds to this request with either a SSH_FXP_NAME or a
+ SSH_FXP_STATUS message. One or more names may be returned at a time.
+ Full status information is returned for each name in order to speed
+ up typical directory listings.
+
+ If there are no more names available to be read, the server MUST
+ respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF.
+
+ When the client no longer wishes to read more names from the
+ directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle
+ should be closed regardless of whether an error has occurred or not.
+
+6.8 Retrieving File Attributes
+
+ Very often, file attributes are automatically returned by
+ SSH_FXP_READDIR. However, sometimes there is need to specifically
+ retrieve the attributes for a named file. This can be done using the
+ SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.
+
+ SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 20]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ follows symbolic links on the server, whereas SSH_FXP_LSTAT does not
+ follow symbolic links. Both have the same format:
+
+ uint32 id
+ string path [UTF-8]
+ uint32 flags
+
+ where `id' is the request identifier, and `path' specifies the file
+ system object for which status is to be returned. The server
+ responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.
+
+ The flags field specify the attribute flags in which the client has
+ particular interest. This is a hint to the server. For example,
+ because retrieving owner / group and acl information can be an
+ expensive operation under some operating systems, the server may
+ choose not to retrieve this information unless the client expresses a
+ specific interest in it.
+
+ The client has no guarantee the server will provide all the fields
+ that it has expressed an interest in.
+
+ SSH_FXP_FSTAT differs from the others in that it returns status
+ information for an open file (identified by the file handle). Its
+ format is as follows:
+
+ uint32 id
+ string handle
+ uint32 flags
+
+ where `id' is the request identifier and `handle' is a file handle
+ returned by SSH_FXP_OPEN. The server responds to this request with
+ SSH_FXP_ATTRS or SSH_FXP_STATUS.
+
+6.9 Setting File Attributes
+
+ File attributes may be modified using the SSH_FXP_SETSTAT and
+ SSH_FXP_FSETSTAT requests. These requests are used for operations
+ such as changing the ownership, permissions or access times, as well
+ as for truncating a file.
+
+ The SSH_FXP_SETSTAT request is of the following format:
+
+ uint32 id
+ string path [UTF-8]
+ ATTRS attrs
+
+ where `id' is the request identifier, `path' specifies the file
+ system object (e.g. file or directory) whose attributes are to be
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 21]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ modified, and `attrs' specifies the modifications to be made to its
+ attributes. Attributes are discussed in more detail in Section
+ ``File Attributes''.
+
+ An error will be returned if the specified file system object does
+ not exist or the user does not have sufficient rights to modify the
+ specified attributes. The server responds to this request with a
+ SSH_FXP_STATUS message.
+
+ The SSH_FXP_FSETSTAT request modifies the attributes of a file which
+ is already open. It has the following format:
+
+ uint32 id
+ string handle
+ ATTRS attrs
+
+ where `id' is the request identifier, `handle' (MUST be returned by
+ SSH_FXP_OPEN) identifies the file whose attributes are to be
+ modified, and `attrs' specifies the modifications to be made to its
+ attributes. Attributes are discussed in more detail in Section
+ ``File Attributes''. The server will respond to this request with
+ SSH_FXP_STATUS.
+
+6.10 Dealing with Symbolic links
+
+ The SSH_FXP_READLINK request may be used to read the target of a
+ symbolic link. It would have a data part as follows:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier and `path' specifies the path
+ name of the symlink to be read.
+
+ The server will respond with a SSH_FXP_NAME packet containing only
+ one name and a dummy attributes value. The name in the returned
+ packet contains the target of the link. If an error occurs, the
+ server may respond with SSH_FXP_STATUS.
+
+ The SSH_FXP_SYMLINK request will create a symbolic link on the
+ server. It is of the following format
+
+ uint32 id
+ string linkpath [UTF-8]
+ string targetpath [UTF-8]
+
+ where `id' is the request identifier, `linkpath' specifies the path
+ name of the symlink to be created and `targetpath' specifies the
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 22]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ target of the symlink. The server shall respond with a
+ SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error
+ condition.
+
+6.11 Canonicalizing the Server-Side Path Name
+
+ The SSH_FXP_REALPATH request can be used to have the server
+ canonicalize any given path name to an absolute path. This is useful
+ for converting path names containing ".." components or relative
+ pathnames without a leading slash into absolute paths. The format of
+ the request is as follows:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier and `path' specifies the path
+ name to be canonicalized. The server will respond with a
+ SSH_FXP_NAME packet containing the name in canonical form and a dummy
+ attributes value. If an error occurs, the server may also respond
+ with SSH_FXP_STATUS.
+
+6.11.1 Best practice for dealing with paths
+
+ The client SHOULD treat the results of SSH_FXP_REALPATH as a
+ canonical absolute path, even if the path does not appear to be
+ absolute. A client that use REALPATH(".") and treats the result as
+ absolute, even if there is no leading slash, will continue to
+ function correctly, even when talking to a Windows NT or VMS style
+ system, where absolute paths may not begin with a slash.
+
+ For example, if the client wishes to change directory up, and the
+ server has returned "c:/x/y/z" from REALPATH, the client SHOULD use
+ "c:/x/y/z/..".
+
+ As a second example, if the client wishes to open the file "x.txt" in
+ the current directory, and server has returned "dka100:/x/y/z" as the
+ canonical path of the directory, the client SHOULD open "dka100:/x/y/
+ z/x.txt"
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 23]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+7. Responses from the Server to the Client
+
+ The server responds to the client using one of a few response
+ packets. All requests can return a SSH_FXP_STATUS response upon
+ failure. When the operation is successful, any of the responses may
+ be returned (depending on the operation). If no data needs to be
+ returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK
+ status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used
+ to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR
+ requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ,
+ SSH_FXP_NAME is used to return one or more file names from a
+ SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is
+ used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and
+ SSH_FXP_FSTAT requests.
+
+ Exactly one response will be returned for each request. Each
+ response packet contains a request identifier which can be used to
+ match each response with the corresponding request. Note that it is
+ legal to have several requests outstanding simultaneously, and the
+ server is allowed to send responses to them in a different order from
+ the order in which the requests were sent (the result of their
+ execution, however, is guaranteed to be as if they had been processed
+ one at a time in the order in which the requests were sent).
+
+ Response packets are of the same general format as request packets.
+ Each response packet begins with the request identifier.
+
+ The format of the data portion of the SSH_FXP_STATUS response is as
+ follows:
+
+ uint32 id
+ uint32 error/status code
+ string error message (ISO-10646 UTF-8 [RFC-2279])
+ string language tag (as defined in [RFC-1766])
+
+ where `id' is the request identifier, and `error/status code'
+ indicates the result of the requested operation. The value SSH_FX_OK
+ indicates success, and all other values indicate failure.
+
+ Currently, the following values are defined (other values may be
+ defined by future versions of this protocol):
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 24]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ #define SSH_FX_OK 0
+ #define SSH_FX_EOF 1
+ #define SSH_FX_NO_SUCH_FILE 2
+ #define SSH_FX_PERMISSION_DENIED 3
+ #define SSH_FX_FAILURE 4
+ #define SSH_FX_BAD_MESSAGE 5
+ #define SSH_FX_NO_CONNECTION 6
+ #define SSH_FX_CONNECTION_LOST 7
+ #define SSH_FX_OP_UNSUPPORTED 8
+ #define SSH_FX_INVALID_HANDLE 9
+ #define SSH_FX_NO_SUCH_PATH 10
+ #define SSH_FX_FILE_ALREADY_EXISTS 11
+ #define SSH_FX_WRITE_PROTECT 12
+
+ SSH_FX_OK
+ Indicates successful completion of the operation.
+
+ SSH_FX_EOF
+ indicates end-of-file condition; for SSH_FX_READ it means that no
+ more data is available in the file, and for SSH_FX_READDIR it
+ indicates that no more files are contained in the directory.
+
+ SSH_FX_NO_SUCH_FILE
+ is returned when a reference is made to a file which does not
+ exist.
+
+ SSH_FX_PERMISSION_DENIED
+ is returned when the authenticated user does not have sufficient
+ permissions to perform the operation.
+
+ SSH_FX_FAILURE
+ is a generic catch-all error message; it should be returned if an
+ error occurs for which there is no more specific error code
+ defined.
+
+ SSH_FX_BAD_MESSAGE
+ may be returned if a badly formatted packet or protocol
+ incompatibility is detected.
+
+ SSH_FX_NO_CONNECTION
+ is a pseudo-error which indicates that the client has no
+ connection to the server (it can only be generated locally by the
+ client, and MUST NOT be returned by servers).
+
+ SSH_FX_CONNECTION_LOST
+ is a pseudo-error which indicates that the connection to the
+ server has been lost (it can only be generated locally by the
+ client, and MUST NOT be returned by servers).
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 25]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ SSH_FX_OP_UNSUPPORTED
+ indicates that an attempt was made to perform an operation which
+ is not supported for the server (it may be generated locally by
+ the client if e.g. the version number exchange indicates that a
+ required feature is not supported by the server, or it may be
+ returned by the server if the server does not implement an
+ operation).
+
+ SSH_FX_INVALID_HANDLE
+ The handle value was invalid.
+
+ SSH_FX_NO_SUCH_PATH
+ The file path does not exist or is invalid.
+
+ SSH_FX_FILE_ALREADY_EXISTS
+ The file already exists.
+
+ SSH_FX_WRITE_PROTECT
+ The file is on read only media, or the media is write protected.
+
+ The SSH_FXP_HANDLE response has the following format:
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is an arbitrary
+ string that identifies an open file or directory on the server. The
+ handle is opaque to the client; the client MUST NOT attempt to
+ interpret or modify it in any way. The length of the handle string
+ MUST NOT exceed 256 data bytes.
+
+ The SSH_FXP_DATA response has the following format:
+
+ uint32 id
+ string data
+
+ where `id' is the request identifier, and `data' is an arbitrary byte
+ string containing the requested data. The data string may be at most
+ the number of bytes requested in a SSH_FXP_READ request, but may also
+ be shorter if end of file is reached or if the read is from something
+ other than a regular file.
+
+ The SSH_FXP_NAME response has the following format:
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 26]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ uint32 id
+ uint32 count
+ repeats count times:
+ string filename [UTF-8]
+ ATTRS attrs
+
+ where `id' is the request identifier, `count' is the number of names
+ returned in this response, and the remaining fields repeat `count'
+ times (so that all three fields are first included for the first
+ file, then for the second file, etc). In the repeated part,
+ `filename' is a file name being returned (for SSH_FXP_READDIR, it
+ will be a relative name within the directory, without any path
+ components; for SSH_FXP_REALPATH it will be an absolute path name),
+ and `attrs' is the attributes of the file as described in Section
+ ``File Attributes''.
+
+ The SSH_FXP_ATTRS response has the following format:
+
+ uint32 id
+ ATTRS attrs
+
+ where `id' is the request identifier, and `attrs' is the returned
+ file attributes as described in Section ``File Attributes''.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 27]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+8. Vendor-Specific Extensions
+
+ The SSH_FXP_EXTENDED request provides a generic extension mechanism
+ for adding vendor-specific commands. The request has the following
+ format:
+
+ uint32 id
+ string extended-request
+ ... any request-specific data ...
+
+ where `id' is the request identifier, and `extended-request' is a
+ string of the format "name@domain", where domain is an internet
+ domain name of the vendor defining the request. The rest of the
+ request is completely vendor-specific, and servers should only
+ attempt to interpret it if they recognize the `extended-request'
+ name.
+
+ The server may respond to such requests using any of the response
+ packets defined in Section ``Responses from the Server to the
+ Client''. Additionally, the server may also respond with a
+ SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does
+ not recognize the `extended-request' name, then the server MUST
+ respond with SSH_FXP_STATUS with error/status set to
+ SSH_FX_OP_UNSUPPORTED.
+
+ The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary
+ extension-specific data from the server to the client. It is of the
+ following format:
+
+ uint32 id
+ ... any request-specific data ...
+
+ There is a range of packet types reserved for use by extensions. In
+ order to avoid collision, extensions that turn on the use of
+ additional packet types should determine those numbers dynamically.
+
+ The suggested way of doing this is have an extension request from the
+ client to the server that enables the extension; the extension
+ response from the server to the client would specify the actual type
+ values to use, in additional to any other data.
+
+ Extension authors should be mindful of the limited range of packet
+ types available (there are only 45 values available) and avoid
+ requiring a new packet type where possible.
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 28]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+9. Security Considerations
+
+ This protocol assumes that it is run over a secure channel and that
+ the endpoints of the channel have been authenticated. Thus, this
+ protocol assumes that it is externally protected from network-level
+ attacks.
+
+ This protocol provides file system access to arbitrary files on the
+ server (only constrained by the server implementation). It is the
+ responsibility of the server implementation to enforce any access
+ controls that may be required to limit the access allowed for any
+ particular user (the user being authenticated externally to this
+ protocol, typically using the SSH User Authentication Protocol [8].
+
+ Care must be taken in the server implementation to check the validity
+ of received file handle strings. The server should not rely on them
+ directly; it MUST check the validity of each handle before relying on
+ it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 29]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+10. Changes from previous protocol versions
+
+ The SSH File Transfer Protocol has changed over time, before it's
+ standardization. The following is a description of the incompatible
+ changes between different versions.
+
+10.1 Changes between versions 4 and 3
+
+ Many of the changes between version 4 and version 3 are to the
+ attribute structure to make it more flexible for non-unix platforms.
+
+ o Make all filenames UTF-8.
+
+ o Added 'newline' extension.
+
+ o Made file attribute owner and group strings so they can actually
+ be used on disparate systems.
+
+ o Added createtime field, and added separate flags for atime,
+ createtime, and mtime so they can be set separately.
+
+ o Split the file type out of the permissions field and into it's own
+ field (which is always present.)
+
+ o Added acl attribute.
+
+ o Added SSH_FXF_TEXT file open flag.
+
+ o Added flags field to the get stat commands so that the client can
+ specifically request information the server might not normally
+ included for performance reasons.
+
+ o Removed the long filename from the names structure-- it can now be
+ built from information available in the attrs structure.
+
+ o Added reserved range of packet numbers for extensions.
+
+ o Added several additional error codes.
+
+ o Change the way version negotiate works slightly. Previously, if
+ the client version were higher than the server version, the server
+ was supposed to 'echo back' the clients version. The server now
+ sends it's own version and the lower of the two is considered to
+ be the one in use.
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 30]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+10.2 Changes between versions 3 and 2
+
+ o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.
+
+ o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were
+ added.
+
+ o The SSH_FXP_STATUS message was changed to include fields `error
+ message' and `language tag'.
+
+
+10.3 Changes between versions 2 and 1
+
+ o The SSH_FXP_RENAME message was added.
+
+
+10.4 Changes between versions 1 and 0
+
+ o Implementation changes, no actual protocol changes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 31]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+11. Trademark Issues
+
+ "ssh" is a registered trademark of SSH Communications Security Corp
+ in the United States and/or other countries.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 32]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+References
+
+ [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and
+ P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January
+ 1999.
+
+ [2] Alvestrand, H., "IETF Policy on Character Sets and Languages",
+ BCP 18, RFC 2277, January 1998.
+
+ [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,
+ C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC
+ 3010, December 2000.
+
+ [4] Institute of Electrical and Electronics Engineers, "Information
+ Technology - Portable Operating System Interface (POSIX) - Part
+ 1: System Application Program Interface (API) [C Language]",
+ IEEE Standard 1003.2, 1996.
+
+ [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Protocol Architecture", draft-ietf-secsh-
+ architecture-13 (work in progress), September 2002.
+
+ [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Protocol Transport Protocol", draft-ietf-secsh-
+ transport-15 (work in progress), September 2002.
+
+ [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16
+ (work in progress), September 2002.
+
+ [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Authentication Protocol", draft-ietf-secsh-
+ userauth-16 (work in progress), September 2002.
+
+
+Authors' Addresses
+
+ Joseph Galbraith
+ VanDyke Software
+ 4848 Tramway Ridge Blvd
+ Suite 101
+ Albuquerque, NM 87111
+ US
+
+ Phone: +1 505 332 5700
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 33]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+ Tatu Ylonen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+ Sami Lehtinen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 34]
+
+Internet-Draft SSH File Transfer Protocol October 2002
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires April 16, 2003 [Page 35]
+
+
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt
new file mode 100644
index 0000000000..9f51883cd2
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-filexfer-04.txt
@@ -0,0 +1,2130 @@
+
+
+
+Secure Shell Working Group J. Galbraith
+Internet-Draft VanDyke Software
+Expires: June 18, 2003 T. Ylonen
+ S. Lehtinen
+ SSH Communications Security Corp
+ December 18, 2002
+
+
+ SSH File Transfer Protocol
+ draft-ietf-secsh-filexfer-04.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on June 18, 2003.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ The SSH File Transfer Protocol provides secure file transfer
+ functionality over any reliable data stream. It is the standard file
+ transfer protocol for use with the SSH2 protocol. This document
+ describes the file transfer protocol and its interface to the SSH2
+ protocol suite.
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 1]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Use with the SSH Connection Protocol . . . . . . . . . . . 4
+ 3. General Packet Format . . . . . . . . . . . . . . . . . . 5
+ 3.1 The use of stderr in the server . . . . . . . . . . . . . 6
+ 4. Protocol Initialization . . . . . . . . . . . . . . . . . 8
+ 4.1 Client Initialization . . . . . . . . . . . . . . . . . . 8
+ 4.2 Server Initialization . . . . . . . . . . . . . . . . . . 8
+ 4.3 Determining Server Newline Convention . . . . . . . . . . 9
+ 5. File Attributes . . . . . . . . . . . . . . . . . . . . . 10
+ 5.1 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 5.2 Type . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 5.3 Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 5.4 Owner and Group . . . . . . . . . . . . . . . . . . . . . 11
+ 5.5 Permissions . . . . . . . . . . . . . . . . . . . . . . . 12
+ 5.6 Times . . . . . . . . . . . . . . . . . . . . . . . . . . 12
+ 5.7 ACL . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
+ 5.8 Extended attributes . . . . . . . . . . . . . . . . . . . 14
+ 6. Requests From the Client to the Server . . . . . . . . . . 15
+ 6.1 Request Synchronization and Reordering . . . . . . . . . . 15
+ 6.2 File Names . . . . . . . . . . . . . . . . . . . . . . . . 16
+ 6.3 Opening, Creating, and Closing Files . . . . . . . . . . . 16
+ 6.4 Reading and Writing . . . . . . . . . . . . . . . . . . . 19
+ 6.5 Removing and Renaming Files . . . . . . . . . . . . . . . 20
+ 6.6 Creating and Deleting Directories . . . . . . . . . . . . 21
+ 6.7 Scanning Directories . . . . . . . . . . . . . . . . . . . 21
+ 6.8 Retrieving File Attributes . . . . . . . . . . . . . . . . 22
+ 6.9 Setting File Attributes . . . . . . . . . . . . . . . . . 23
+ 6.10 Dealing with Symbolic links . . . . . . . . . . . . . . . 24
+ 6.11 Canonicalizing the Server-Side Path Name . . . . . . . . . 25
+ 6.11.1 Best practice for dealing with paths . . . . . . . . . . . 25
+ 7. Responses from the Server to the Client . . . . . . . . . 26
+ 8. Vendor-Specific Extensions . . . . . . . . . . . . . . . . 30
+ 9. Security Considerations . . . . . . . . . . . . . . . . . 31
+ 10. Changes from previous protocol versions . . . . . . . . . 32
+ 10.1 Changes between versions 4 and 3 . . . . . . . . . . . . . 32
+ 10.2 Changes between versions 3 and 2 . . . . . . . . . . . . . 33
+ 10.3 Changes between versions 2 and 1 . . . . . . . . . . . . . 33
+ 10.4 Changes between versions 1 and 0 . . . . . . . . . . . . . 33
+ 11. Trademark Issues . . . . . . . . . . . . . . . . . . . . . 34
+ References . . . . . . . . . . . . . . . . . . . . . . . . 35
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . 35
+ Intellectual Property and Copyright Statements . . . . . . 37
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 2]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+1. Introduction
+
+ This protocol provides secure file transfer (and more generally file
+ system access) functionality over a reliable data stream, such as a
+ channel in the SSH2 protocol [5].
+
+ This protocol is designed so that it could be used to implement a
+ secure remote file system service, as well as a secure file transfer
+ service.
+
+ This protocol assumes that it runs over a secure channel, and that
+ the server has already authenticated the user at the client end, and
+ that the identity of the client user is externally available to the
+ server implementation.
+
+ In general, this protocol follows a simple request-response model.
+ Each request and response contains a sequence number and multiple
+ requests may be pending simultaneously. There are a relatively large
+ number of different request messages, but a small number of possible
+ response messages. Each request has one or more response messages
+ that may be returned in result (e.g., a read either returns data or
+ reports error status).
+
+ The packet format descriptions in this specification follow the
+ notation presented in the secsh architecture draft. [5]
+
+ Even though this protocol is described in the context of the SSH2
+ protocol, this protocol is general and independent of the rest of the
+ SSH2 protocol suite. It could be used in a number of different
+ applications, such as secure file transfer over TLS RFC 2246 [1] and
+ transfer of management information in VPN applications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 3]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+2. Use with the SSH Connection Protocol
+
+ When used with the SSH2 Protocol suite, this protocol is intended to
+ be used from the SSH Connection Protocol [7] as a subsystem, as
+ described in section ``Starting a Shell or a Command''. The
+ subsystem name used with this protocol is "sftp".
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 4]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+3. General Packet Format
+
+ All packets transmitted over the secure connection are of the
+ following format:
+
+ uint32 length
+ byte type
+ byte[length - 1] data payload
+
+ That is, they are just data preceded by 32-bit length and 8-bit type
+ fields. The `length' is the length of the data area, and does not
+ include the `length' field itself. The format and interpretation of
+ the data area depends on the packet type.
+
+ All packet descriptions below only specify the packet type and the
+ data that goes into the data field. Thus, they should be prefixed by
+ the `length' and `type' fields.
+
+ The maximum size of a packet is in practice determined by the client
+ (the maximum size of read or write requests that it sends, plus a few
+ bytes of packet overhead). All servers SHOULD support packets of at
+ least 34000 bytes (where the packet size refers to the full length,
+ including the header above). This should allow for reads and writes
+ of at most 32768 bytes.
+
+ There is no limit on the number of outstanding (non-acknowledged)
+ requests that the client may send to the server. In practice this is
+ limited by the buffering available on the data stream and the queuing
+ performed by the server. If the server's queues are full, it should
+ not read any more data from the stream, and flow control will prevent
+ the client from sending more requests. Note, however, that while
+ there is no restriction on the protocol level, the client's API may
+ provide a limit in order to prevent infinite queuing of outgoing
+ requests at the client.
+
+ The following values are defined for packet types.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 5]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ #define SSH_FXP_INIT 1
+ #define SSH_FXP_VERSION 2
+ #define SSH_FXP_OPEN 3
+ #define SSH_FXP_CLOSE 4
+ #define SSH_FXP_READ 5
+ #define SSH_FXP_WRITE 6
+ #define SSH_FXP_LSTAT 7
+ #define SSH_FXP_FSTAT 8
+ #define SSH_FXP_SETSTAT 9
+ #define SSH_FXP_FSETSTAT 10
+ #define SSH_FXP_OPENDIR 11
+ #define SSH_FXP_READDIR 12
+ #define SSH_FXP_REMOVE 13
+ #define SSH_FXP_MKDIR 14
+ #define SSH_FXP_RMDIR 15
+ #define SSH_FXP_REALPATH 16
+ #define SSH_FXP_STAT 17
+ #define SSH_FXP_RENAME 18
+ #define SSH_FXP_READLINK 19
+ #define SSH_FXP_SYMLINK 20
+
+ #define SSH_FXP_STATUS 101
+ #define SSH_FXP_HANDLE 102
+ #define SSH_FXP_DATA 103
+ #define SSH_FXP_NAME 104
+ #define SSH_FXP_ATTRS 105
+
+ #define SSH_FXP_EXTENDED 200
+ #define SSH_FXP_EXTENDED_REPLY 201
+
+ RESERVED_FOR_EXTENSIONS 210-255
+
+ Additional packet types should only be defined if the protocol
+ version number (see Section ``Protocol Initialization'') is
+ incremented, and their use MUST be negotiated using the version
+ number. However, the SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY
+ packets can be used to implement vendor-specific extensions. See
+ Section ``Vendor-Specific-Extensions'' for more details.
+
+3.1 The use of stderr in the server
+
+ Packets are sent and received on stdout and stdin. Data sent on
+ stderr by the server SHOULD be considered debug or supplemental error
+ information, and MAY be displayed to the user.
+
+ For example, during initialization, there is no client request
+ active, so errors or warning information cannot be sent to the client
+ as part of the SFTP protocol at this early stage. However, the
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 6]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ errors or warnings MAY be sent as stderr text.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 7]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+4. Protocol Initialization
+
+ When the file transfer protocol starts, the client first sends a
+ SSH_FXP_INIT (including its version number) packet to the server.
+ The server responds with a SSH_FXP_VERSION packet, supplying the
+ lowest of its own and the client's version number. Both parties
+ should from then on adhere to particular version of the protocol.
+
+ The version number of the protocol specified in this document is 4.
+ The version number should be incremented for each incompatible
+ revision of this protocol.
+
+4.1 Client Initialization
+
+ The SSH_FXP_INIT packet (from client to server) has the following
+ data:
+
+ uint32 version
+
+ Version 3 of this protocol allowed clients to include extensions in
+ the SSH_FXP_INIT packet; however, this can cause interoperability
+ problems with version 1 and version 2 servers because the client must
+ send this packet before knowing the servers version.
+
+ In this version of the protocol, clients MUST use the
+ SSH_FXP_EXTENDED packet to send extensions to the server after
+ version exchange has completed. Clients MUST NOT include extensions
+ in the version packet. This will prevent interoperability problems
+ with older servers
+
+4.2 Server Initialization
+
+ The SSH_FXP_VERSION packet (from server to client) has the following
+ data:
+
+ uint32 version
+ <extension data>
+
+ 'version' is the lower of the protocol version supported by the
+ server and the version number received from the client.
+
+ The extension data may be empty, or may be a sequence of
+
+ string extension_name
+ string extension_data
+
+ pairs (both strings MUST always be present if one is, but the
+ `extension_data' string may be of zero length). If present, these
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 8]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ strings indicate extensions to the baseline protocol. The
+ `extension_name' field(s) identify the name of the extension. The
+ name should be of the form "name@domain", where the domain is the DNS
+ domain name of the organization defining the extension. Additional
+ names that are not of this format may be defined later by the IETF.
+ Implementations MUST silently ignore any extensions whose name they
+ do not recognize.
+
+4.3 Determining Server Newline Convention
+
+ In order to correctly process text files in a cross platform
+ compatible way, the newline convention must be converted from that of
+ the server to that of the client, or, during an upload, from that of
+ the client to that of the server.
+
+ Versions 3 and prior of this protocol made no provisions for
+ processing text files. Many clients implemented some sort of
+ conversion algorithm, but without either a 'canonical' on the wire
+ format or knowledge of the servers newline convention, correct
+ conversion was not always possible.
+
+ Starting with Version 4, the SSH_FXF_TEXT file open flag (Section
+ 6.3) makes it possible to request that the server translate a file to
+ a 'canonical' on the wire format. This format uses \r\n as the line
+ separator.
+
+ Servers for systems using multiple newline characters (for example,
+ Mac OS X or VMS) or systems using counted records, MUST translate to
+ the canonical form.
+
+ However, to ease the burden of implementation on servers that use a
+ single, simple separator sequence, the following extension allows the
+ canonical format to be changed.
+
+ string "newline"
+ string new-canonical-separator (usually "\r" or "\n" or "\r\n")
+
+ All clients MUST support this extension.
+
+ When processing text files, clients SHOULD NOT translate any
+ character or sequence that is not an exact match of the servers
+ newline separator.
+
+ In particular, if the newline sequence being used is the canonical
+ "\r\n" sequence, a lone \r or a lone \n SHOULD be written through
+ without change.
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 9]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+5. File Attributes
+
+ A new compound data type is defined for encoding file attributes.
+ The same encoding is used both when returning file attributes from
+ the server and when sending file attributes to the server. When
+ sending it to the server, the flags field specifies which attributes
+ are included, and the server will use default values for the
+ remaining attributes (or will not modify the values of remaining
+ attributes). When receiving attributes from the server, the flags
+ specify which attributes are included in the returned data. The
+ server normally returns all attributes it knows about.
+
+ uint32 flags
+ byte type always present
+ uint64 size present only if flag SIZE
+ string owner present only if flag OWNERGROUP
+ string group present only if flag OWNERGROUP
+ uint32 permissions present only if flag PERMISSIONS
+ uint64 atime present only if flag ACCESSTIME
+ uint32 atime_nseconds present only if flag SUBSECOND_TIMES
+ uint64 createtime present only if flag CREATETIME
+ uint32 createtime_nseconds present only if flag SUBSECOND_TIMES
+ uint64 mtime present only if flag MODIFYTIME
+ uint32 mtime_nseconds present only if flag SUBSECOND_TIMES
+ string acl present only if flag ACL
+ uint32 extended_count present only if flag EXTENDED
+ string extended_type
+ string extended_data
+ ... more extended data (extended_type - extended_data pairs),
+ so that number of pairs equals extended_count
+
+
+5.1 Flags
+
+ The `flags' specify which of the fields are present. Those fields
+ for which the corresponding flag is not set are not present (not
+ included in the packet). New flags can only be added by incrementing
+ the protocol version number (or by using the extension mechanism
+ described below).
+
+ The flags bits are defined to have the following values:
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 10]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ #define SSH_FILEXFER_ATTR_SIZE 0x00000001
+ #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000040
+ #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
+ #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
+ #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
+ #define SSH_FILEXFER_ATTR_ACL 0x00000040
+ #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
+ #define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x00000100
+ #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
+
+ In previous versions of this protocol flags value 0x00000002 was
+ SSH_FILEXFER_ATTR_UIDGID. This value is now unused, and OWNERGROUP
+ was given a new value in order to ease implementation burden.
+ 0x00000002 MUST NOT appear in the mask. Some future version of this
+ protocol may reuse flag 0x00000002.
+
+5.2 Type
+
+ The type field is always present. The following types are defined:
+
+ #define SSH_FILEXFER_TYPE_REGULAR 1
+ #define SSH_FILEXFER_TYPE_DIRECTORY 2
+ #define SSH_FILEXFER_TYPE_SYMLINK 3
+ #define SSH_FILEXFER_TYPE_SPECIAL 4
+ #define SSH_FILEXFER_TYPE_UNKNOWN 5
+
+ On a POSIX system, these values would be derived from the permission
+ field.
+
+5.3 Size
+
+ The `size' field specifies the size of the file on disk, in bytes.
+ If it is present during file creation, it should be considered a hint
+ as to the files eventual size.
+
+ Files opened with the SSH_FXF_TEXT flag may have a size that is
+ greater or less than the value of the size field.
+
+5.4 Owner and Group
+
+ The `owner' and `group' fields are represented as UTF-8 strings; this
+ is the form used by NFS v4. See NFS version 4 Protocol. [3] The
+ following text is selected quotations from section 5.6.
+
+ To avoid a representation that is tied to a particular underlying
+ implementation at the client or server, the use of UTF-8 strings has
+ been chosen. The string should be of the form user@dns_domain".
+ This will allow for a client and server that do not use the same
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 11]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ local representation the ability to translate to a common syntax that
+ can be interpreted by both. In the case where there is no
+ translation available to the client or server, the attribute value
+ must be constructed without the "@". Therefore, the absence of the @
+ from the owner or owner_group attribute signifies that no translation
+ was available and the receiver of the attribute should not place any
+ special meaning with the attribute value. Even though the attribute
+ value can not be translated, it may still be useful. In the case of
+ a client, the attribute string may be used for local display of
+ ownership.
+
+5.5 Permissions
+
+ The `permissions' field contains a bit mask of file permissions as
+ defined by POSIX [1].
+
+5.6 Times
+
+ The 'atime', 'createtime', and 'mtime' contain the access, creation,
+ and modification times of the files, respectively. They are
+ represented as seconds from Jan 1, 1970 in UTC.
+
+ A negative value indicates number of seconds before Jan 1, 1970. In
+ both cases, if the SSH_FILEXFER_ATTR_SUBSECOND_TIMES flag is set, the
+ nseconds field is to be added to the seconds field for the final time
+ representation. For example, if the time to be represented is
+ one-half second before 0 hour January 1, 1970, the seconds field
+ would have a value of negative one (-1) and the nseconds fields would
+ have a value of one-half second (500000000). Values greater than
+ 999,999,999 for nseconds are considered invalid.
+
+5.7 ACL
+
+ The 'ACL' field contains an ACL similar to that defined in section
+ 5.9 of NFS version 4 Protocol [3].
+
+ uint32 ace-count
+
+ repeated ace-count time:
+ uint32 ace-type
+ uint32 ace-flag
+ uint32 ace-mask
+ string who [UTF-8]
+
+ ace-type is one of the following four values (taken from NFS Version
+ 4 Protocol [3]:
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 12]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;
+ const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;
+ const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;
+ const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;
+
+ ace-flag is a combination of the following flag values. See NFS
+ Version 4 Protocol [3] section 5.9.2:
+
+ const ACE4_FILE_INHERIT_ACE = 0x00000001;
+ const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;
+ const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;
+ const ACE4_INHERIT_ONLY_ACE = 0x00000008;
+ const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;
+ const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;
+ const ACE4_IDENTIFIER_GROUP = 0x00000040;
+
+ ace-mask is any combination of the following flags (taken from NFS
+ Version 4 Protocol [3] section 5.9.3:
+
+ const ACE4_READ_DATA = 0x00000001;
+ const ACE4_LIST_DIRECTORY = 0x00000001;
+ const ACE4_WRITE_DATA = 0x00000002;
+ const ACE4_ADD_FILE = 0x00000002;
+ const ACE4_APPEND_DATA = 0x00000004;
+ const ACE4_ADD_SUBDIRECTORY = 0x00000004;
+ const ACE4_READ_NAMED_ATTRS = 0x00000008;
+ const ACE4_WRITE_NAMED_ATTRS = 0x00000010;
+ const ACE4_EXECUTE = 0x00000020;
+ const ACE4_DELETE_CHILD = 0x00000040;
+ const ACE4_READ_ATTRIBUTES = 0x00000080;
+ const ACE4_WRITE_ATTRIBUTES = 0x00000100;
+ const ACE4_DELETE = 0x00010000;
+ const ACE4_READ_ACL = 0x00020000;
+ const ACE4_WRITE_ACL = 0x00040000;
+ const ACE4_WRITE_OWNER = 0x00080000;
+ const ACE4_SYNCHRONIZE = 0x00100000;
+
+ who is a UTF-8 string of the form described in 'Owner and Group'
+ (Section 5.4)
+
+ Also, as per '5.9.4 ACE who' [3] there are several identifiers that
+ need to be understood universally. Some of these identifiers cannot
+ be understood when an client access the server, but have meaning when
+ a local process accesses the file. The ability to display and modify
+ these permissions is permitted over SFTP.
+
+ OWNER The owner of the file.
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 13]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ GROUP The group associated with the file.
+
+ EVERYONE The world.
+
+ INTERACTIVE Accessed from an interactive terminal.
+
+ NETWORK Accessed via the network.
+
+ DIALUP Accessed as a dialup user to the server.
+
+ BATCH Accessed from a batch job.
+
+ ANONYMOUS Accessed without any authentication.
+
+ AUTHENTICATED Any authenticated user (opposite of ANONYMOUS).
+
+ SERVICE Access from a system service.
+
+ To avoid conflict, these special identifiers are distinguish by an
+ appended "@" and should appear in the form "xxxx@" (note: no domain
+ name after the "@"). For example: ANONYMOUS@.
+
+5.8 Extended attributes
+
+ The SSH_FILEXFER_ATTR_EXTENDED flag provides a general extension
+ mechanism for vendor-specific extensions. If the flag is specified,
+ then the `extended_count' field is present. It specifies the number
+ of extended_type-extended_data pairs that follow. Each of these
+ pairs specifies an extended attribute. For each of the attributes,
+ the extended_type field should be a string of the format
+ "name@domain", where "domain" is a valid, registered domain name and
+ "name" identifies the method. The IETF may later standardize certain
+ names that deviate from this format (e.g., that do not contain the
+ "@" sign). The interpretation of `extended_data' depends on the
+ type. Implementations SHOULD ignore extended data fields that they
+ do not understand.
+
+ Additional fields can be added to the attributes by either defining
+ additional bits to the flags field to indicate their presence, or by
+ defining extended attributes for them. The extended attributes
+ mechanism is recommended for most purposes; additional flags bits
+ should only be defined by an IETF standards action that also
+ increments the protocol version number. The use of such new fields
+ MUST be negotiated by the version number in the protocol exchange.
+ It is a protocol error if a packet with unsupported protocol bits is
+ received.
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 14]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+6. Requests From the Client to the Server
+
+ Requests from the client to the server represent the various file
+ system operations. Each request begins with an `id' field, which is
+ a 32-bit identifier identifying the request (selected by the client).
+ The same identifier will be returned in the response to the request.
+ One possible implementation is a monotonically increasing request
+ sequence number (modulo 2^32).
+
+ Many operations in the protocol operate on open files. The
+ SSH_FXP_OPEN request can return a file handle (which is an opaque
+ variable-length string) which may be used to access the file later
+ (e.g. in a read operation). The client MUST NOT send requests the
+ server with bogus or closed handles. However, the server MUST
+ perform adequate checks on the handle in order to avoid security
+ risks due to fabricated handles.
+
+ This design allows either stateful and stateless server
+ implementation, as well as an implementation which caches state
+ between requests but may also flush it. The contents of the file
+ handle string are entirely up to the server and its design. The
+ client should not modify or attempt to interpret the file handle
+ strings.
+
+ The file handle strings MUST NOT be longer than 256 bytes.
+
+6.1 Request Synchronization and Reordering
+
+ The protocol and implementations MUST process requests relating to
+ the same file in the order in which they are received. In other
+ words, if an application submits multiple requests to the server, the
+ results in the responses will be the same as if it had sent the
+ requests one at a time and waited for the response in each case. For
+ example, the server may process non-overlapping read/write requests
+ to the same file in parallel, but overlapping reads and writes cannot
+ be reordered or parallelized. However, there are no ordering
+ restrictions on the server for processing requests from two different
+ file transfer connections. The server may interleave and parallelize
+ them at will.
+
+ There are no restrictions on the order in which responses to
+ outstanding requests are delivered to the client, except that the
+ server must ensure fairness in the sense that processing of no
+ request will be indefinitely delayed even if the client is sending
+ other requests so that there are multiple outstanding requests all
+ the time.
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 15]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+6.2 File Names
+
+ This protocol represents file names as strings. File names are
+ assumed to use the slash ('/') character as a directory separator.
+
+ File names starting with a slash are "absolute", and are relative to
+ the root of the file system. Names starting with any other character
+ are relative to the user's default directory (home directory). Note
+ that identifying the user is assumed to take place outside of this
+ protocol.
+
+ Servers SHOULD interpret a path name component ".." as referring to
+ the parent directory, and "." as referring to the current directory.
+ If the server implementation limits access to certain parts of the
+ file system, it must be extra careful in parsing file names when
+ enforcing such restrictions. There have been numerous reported
+ security bugs where a ".." in a path name has allowed access outside
+ the intended area.
+
+ An empty path name is valid, and it refers to the user's default
+ directory (usually the user's home directory).
+
+ Otherwise, no syntax is defined for file names by this specification.
+ Clients should not make any other assumptions; however, they can
+ splice path name components returned by SSH_FXP_READDIR together
+ using a slash ('/') as the separator, and that will work as expected.
+
+ In order to comply with IETF Policy on Character Sets and Languages
+ [2], all filenames are to be encoded in UTF-8. The shortest valid
+ UTF-8 encoding of the UNICODE data MUST be used. The server is
+ responsible for converting the UNICODE data to whatever canonical
+ form it requires.
+
+ For example, if the server requires that precomposed characters
+ always be used, the server MUST NOT assume the filename as sent by
+ the client has this attribute, but must do this normalization itself.
+
+ It is understood that the lack of well-defined semantics for file
+ names may cause interoperability problems between clients and servers
+ using radically different operating systems. However, this approach
+ is known to work acceptably with most systems, and alternative
+ approaches that e.g. treat file names as sequences of structured
+ components are quite complicated.
+
+6.3 Opening, Creating, and Closing Files
+
+ Files are opened and created using the SSH_FXP_OPEN message, whose
+ data part is as follows:
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 16]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ uint32 id
+ string filename [UTF-8]
+ uint32 pflags
+ ATTRS attrs
+
+ The `id' field is the request identifier as for all requests.
+
+ The `filename' field specifies the file name. See Section ``File
+ Names'' for more information.
+
+ The `pflags' field is a bitmask. The following bits have been
+ defined.
+
+ #define SSH_FXF_READ 0x00000001
+ #define SSH_FXF_WRITE 0x00000002
+ #define SSH_FXF_APPEND 0x00000004
+ #define SSH_FXF_CREAT 0x00000008
+ #define SSH_FXF_TRUNC 0x00000010
+ #define SSH_FXF_EXCL 0x00000020
+ #define SSH_FXF_TEXT 0x00000040
+
+ These have the following meanings:
+
+ SSH_FXF_READ
+ Open the file for reading.
+
+ SSH_FXF_WRITE
+ Open the file for writing. If both this and SSH_FXF_READ are
+ specified, the file is opened for both reading and writing.
+
+ SSH_FXF_APPEND
+ Force all writes to append data at the end of the file. The
+ offset parameter to write will be ignored.
+
+ SSH_FXF_CREAT
+ If this flag is specified, then a new file will be created if one
+ does not already exist (if O_TRUNC is specified, the new file will
+ be truncated to zero length if it previously exists).
+
+ SSH_FXF_TRUNC
+ Forces an existing file with the same name to be truncated to zero
+ length when creating a file by specifying SSH_FXF_CREAT.
+ SSH_FXF_CREAT MUST also be specified if this flag is used.
+
+ SSH_FXF_EXCL
+ Causes the request to fail if the named file already exists.
+ SSH_FXF_CREAT MUST also be specified if this flag is used.
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 17]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ SSH_FXF_TEXT
+ Indicates that the server should treat the file as text and
+ convert it to the canonical newline convention in use. (See
+ Determining Server Newline Convention. (Section 4.3)
+
+ When a file is opened with the FXF_TEXT flag, the offset field in
+ both the read and write function are ignored.
+
+ Servers MUST correctly process multiple parallel reads and writes
+ correctly in this mode. Naturally, it is permissible for them to
+ do this by serializing the requests. It would not be possible for
+ a client to reliably detect a server that does not implement
+ parallel writes in time to prevent damage.
+
+ Clients SHOULD use the SSH_FXF_APPEND flag to append data to a
+ text file rather then using write with a calculated offset.
+
+ To support seeks on text file the following SSH_FXP_EXTENDED
+ packet is defined.
+
+
+
+ string "text-seek"
+ string file-handle
+ uint64 line-number
+
+ line-number is the index of the line number to seek to, where byte
+ 0 in the file is line number 0, and the byte directly following
+ the first newline sequence in the file is line number 1 and so on.
+
+ The response to a "text-seek" request is an SSH_FXP_STATUS
+ message.
+
+ An attempt to seek past the end-of-file should result in a
+ SSH_FX_EOF status.
+
+ Servers SHOULD support at least one "text-seek" in order to
+ support resume. However, a client MUST be prepared to receive
+ SSH_FX_OP_UNSUPPORTED when attempting a "text-seek" operation.
+ The client can then try a fall-back strategy, if it has one.
+
+ Clients MUST be prepared to handle SSH_FX_OP_UNSUPPORTED returned
+ for read or write operations that are not sequential.
+
+ The `attrs' field specifies the initial attributes for the file.
+ Default values will be used for those attributes that are not
+ specified. See Section ``File Attributes'' for more information.
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 18]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ The response to this message will be either SSH_FXP_HANDLE (if the
+ operation is successful) or SSH_FXP_STATUS (if the operation fails).
+
+ A file is closed by using the SSH_FXP_CLOSE request. Its data field
+ has the following format:
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is a handle
+ previously returned in the response to SSH_FXP_OPEN or
+ SSH_FXP_OPENDIR. The handle becomes invalid immediately after this
+ request has been sent.
+
+ The response to this request will be a SSH_FXP_STATUS message. One
+ should note that on some server platforms even a close can fail.
+ This can happen e.g. if the server operating system caches writes,
+ and an error occurs while flushing cached writes during the close.
+
+6.4 Reading and Writing
+
+ Once a file has been opened, it can be read using the following
+ message:
+
+ byte SSH_FXP_READ
+ uint32 id
+ string handle
+ uint64 offset
+ uint32 len
+
+ where `id' is the request identifier, `handle' is an open file handle
+ returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) relative
+ to the beginning of the file from where to start reading, and `len'
+ is the maximum number of bytes to read.
+
+ In response to this request, the server will read as many bytes as it
+ can from the file (up to `len'), and return them in a SSH_FXP_DATA
+ message. If an error occurs or EOF is encountered before reading any
+ data, the server will respond with SSH_FXP_STATUS.
+
+ For normal disk files, it is normally guaranteed that this will read
+ the specified number of bytes, or up to end of file. However, if the
+ read length is very long, the server may truncate it if it doesn't
+ support packets of that length. See General Packet Format (Section
+ 3).
+
+ For e.g. device files this may return fewer bytes than requested.
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 19]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ Writing to a file is achieved using the following message:
+
+ byte SSH_FXP_WRITE
+ uint32 id
+ string handle
+ uint64 offset
+ string data
+
+ where `id' is a request identifier, `handle' is a file handle
+ returned by SSH_FXP_OPEN, `offset' is the offset (in bytes) from the
+ beginning of the file where to start writing, and `data' is the data
+ to be written.
+
+ The write will extend the file if writing beyond the end of the file.
+ It is legal to write way beyond the end of the file; the semantics
+ are to write zeroes from the end of the file to the specified offset
+ and then the data. On most operating systems, such writes do not
+ allocate disk space but instead leave "holes" in the file.
+
+ The server responds to a write request with a SSH_FXP_STATUS message.
+
+6.5 Removing and Renaming Files
+
+ Files can be removed using the SSH_FXP_REMOVE message. It has the
+ following format:
+
+ uint32 id
+ string filename [UTF-8]
+
+ where `id' is the request identifier and `filename' is the name of
+ the file to be removed. See Section ``File Names'' for more
+ information. This request cannot be used to remove directories.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+ message.
+
+ Files (and directories) can be renamed using the SSH_FXP_RENAME
+ message. Its data is as follows:
+
+ uint32 id
+ string oldpath [UTF-8]
+ string newpath [UTF-8]
+
+ where `id' is the request identifier, `oldpath' is the name of an
+ existing file or directory, and `newpath' is the new name for the
+ file or directory. It is an error if there already exists a file
+ with the name specified by newpath. The server may also fail rename
+ requests in other situations, for example if `oldpath' and `newpath'
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 20]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ point to different file systems on the server.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+ message.
+
+6.6 Creating and Deleting Directories
+
+ New directories can be created using the SSH_FXP_MKDIR request. It
+ has the following format:
+
+ uint32 id
+ string path [UTF-8]
+ ATTRS attrs
+
+ where `id' is the request identifier.
+
+ `path' specifies the directory to be created. See Section ``File
+ Names'' for more information on file names.
+
+ `attrs' specifies the attributes that should be applied to it upon
+ creation. Attributes are discussed in more detail in Section ``File
+ Attributes''.
+
+ The server will respond to this request with a SSH_FXP_STATUS
+ message. If a file or directory with the specified path already
+ exists, an error will be returned.
+
+ Directories can be removed using the SSH_FXP_RMDIR request, which has
+ the following format:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier, and `path' specifies the
+ directory to be removed. See Section ``File Names'' for more
+ information on file names.
+
+ The server responds to this request with a SSH_FXP_STATUS message.
+ Errors may be returned from this operation for various reasons,
+ including, but not limited to, the path does not exist, the path does
+ not refer to a directory object, the directory is not empty, or the
+ user has insufficient access or permission to perform the requested
+ operation.
+
+6.7 Scanning Directories
+
+ The files in a directory can be listed using the SSH_FXP_OPENDIR and
+ SSH_FXP_READDIR requests. Each SSH_FXP_READDIR request returns one
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 21]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ or more file names with full file attributes for each file. The
+ client should call SSH_FXP_READDIR repeatedly until it has found the
+ file it is looking for or until the server responds with a
+ SSH_FXP_STATUS message indicating an error (normally SSH_FX_EOF if
+ there are no more files in the directory). The client should then
+ close the handle using the SSH_FXP_CLOSE request.
+
+ The SSH_FXP_OPENDIR opens a directory for reading. It has the
+ following format:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier and `path' is the path name of
+ the directory to be listed (without any trailing slash). See Section
+ ``File Names'' for more information on file names. This will return
+ an error if the path does not specify a directory or if the directory
+ is not readable. The server will respond to this request with either
+ a SSH_FXP_HANDLE or a SSH_FXP_STATUS message.
+
+ Once the directory has been successfully opened, files (and
+ directories) contained in it can be listed using SSH_FXP_READDIR
+ requests. These are of the format
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is a handle
+ returned by SSH_FXP_OPENDIR. (It is a protocol error to attempt to
+ use an ordinary file handle returned by SSH_FXP_OPEN.)
+
+ The server responds to this request with either a SSH_FXP_NAME or a
+ SSH_FXP_STATUS message. One or more names may be returned at a time.
+ Full status information is returned for each name in order to speed
+ up typical directory listings.
+
+ If there are no more names available to be read, the server MUST
+ respond with a SSH_FXP_STATUS message with error code of SSH_FX_EOF.
+
+ When the client no longer wishes to read more names from the
+ directory, it SHOULD call SSH_FXP_CLOSE for the handle. The handle
+ should be closed regardless of whether an error has occurred or not.
+
+6.8 Retrieving File Attributes
+
+ Very often, file attributes are automatically returned by
+ SSH_FXP_READDIR. However, sometimes there is need to specifically
+ retrieve the attributes for a named file. This can be done using the
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 22]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ SSH_FXP_STAT, SSH_FXP_LSTAT and SSH_FXP_FSTAT requests.
+
+ SSH_FXP_STAT and SSH_FXP_LSTAT only differ in that SSH_FXP_STAT
+ follows symbolic links on the server, whereas SSH_FXP_LSTAT does not
+ follow symbolic links. Both have the same format:
+
+ uint32 id
+ string path [UTF-8]
+ uint32 flags
+
+ where `id' is the request identifier, and `path' specifies the file
+ system object for which status is to be returned. The server
+ responds to this request with either SSH_FXP_ATTRS or SSH_FXP_STATUS.
+
+ The flags field specify the attribute flags in which the client has
+ particular interest. This is a hint to the server. For example,
+ because retrieving owner / group and acl information can be an
+ expensive operation under some operating systems, the server may
+ choose not to retrieve this information unless the client expresses a
+ specific interest in it.
+
+ The client has no guarantee the server will provide all the fields
+ that it has expressed an interest in.
+
+ SSH_FXP_FSTAT differs from the others in that it returns status
+ information for an open file (identified by the file handle). Its
+ format is as follows:
+
+ uint32 id
+ string handle
+ uint32 flags
+
+ where `id' is the request identifier and `handle' is a file handle
+ returned by SSH_FXP_OPEN. The server responds to this request with
+ SSH_FXP_ATTRS or SSH_FXP_STATUS.
+
+6.9 Setting File Attributes
+
+ File attributes may be modified using the SSH_FXP_SETSTAT and
+ SSH_FXP_FSETSTAT requests. These requests are used for operations
+ such as changing the ownership, permissions or access times, as well
+ as for truncating a file.
+
+ The SSH_FXP_SETSTAT request is of the following format:
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 23]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ uint32 id
+ string path [UTF-8]
+ ATTRS attrs
+
+ where `id' is the request identifier, `path' specifies the file
+ system object (e.g. file or directory) whose attributes are to be
+ modified, and `attrs' specifies the modifications to be made to its
+ attributes. Attributes are discussed in more detail in Section
+ ``File Attributes''.
+
+ An error will be returned if the specified file system object does
+ not exist or the user does not have sufficient rights to modify the
+ specified attributes. The server responds to this request with a
+ SSH_FXP_STATUS message.
+
+ The SSH_FXP_FSETSTAT request modifies the attributes of a file which
+ is already open. It has the following format:
+
+ uint32 id
+ string handle
+ ATTRS attrs
+
+ where `id' is the request identifier, `handle' (MUST be returned by
+ SSH_FXP_OPEN) identifies the file whose attributes are to be
+ modified, and `attrs' specifies the modifications to be made to its
+ attributes. Attributes are discussed in more detail in Section
+ ``File Attributes''. The server will respond to this request with
+ SSH_FXP_STATUS.
+
+6.10 Dealing with Symbolic links
+
+ The SSH_FXP_READLINK request may be used to read the target of a
+ symbolic link. It would have a data part as follows:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier and `path' specifies the path
+ name of the symlink to be read.
+
+ The server will respond with a SSH_FXP_NAME packet containing only
+ one name and a dummy attributes value. The name in the returned
+ packet contains the target of the link. If an error occurs, the
+ server may respond with SSH_FXP_STATUS.
+
+ The SSH_FXP_SYMLINK request will create a symbolic link on the
+ server. It is of the following format
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 24]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ uint32 id
+ string linkpath [UTF-8]
+ string targetpath [UTF-8]
+
+ where `id' is the request identifier, `linkpath' specifies the path
+ name of the symlink to be created and `targetpath' specifies the
+ target of the symlink. The server shall respond with a
+ SSH_FXP_STATUS indicating either success (SSH_FX_OK) or an error
+ condition.
+
+6.11 Canonicalizing the Server-Side Path Name
+
+ The SSH_FXP_REALPATH request can be used to have the server
+ canonicalize any given path name to an absolute path. This is useful
+ for converting path names containing ".." components or relative
+ pathnames without a leading slash into absolute paths. The format of
+ the request is as follows:
+
+ uint32 id
+ string path [UTF-8]
+
+ where `id' is the request identifier and `path' specifies the path
+ name to be canonicalized. The server will respond with a
+ SSH_FXP_NAME packet containing the name in canonical form and a dummy
+ attributes value. If an error occurs, the server may also respond
+ with SSH_FXP_STATUS.
+
+6.11.1 Best practice for dealing with paths
+
+ The client SHOULD treat the results of SSH_FXP_REALPATH as a
+ canonical absolute path, even if the path does not appear to be
+ absolute. A client that use REALPATH(".") and treats the result as
+ absolute, even if there is no leading slash, will continue to
+ function correctly, even when talking to a Windows NT or VMS style
+ system, where absolute paths may not begin with a slash.
+
+ For example, if the client wishes to change directory up, and the
+ server has returned "c:/x/y/z" from REALPATH, the client SHOULD use
+ "c:/x/y/z/..".
+
+ As a second example, if the client wishes to open the file "x.txt" in
+ the current directory, and server has returned "dka100:/x/y/z" as the
+ canonical path of the directory, the client SHOULD open "dka100:/x/y/
+ z/x.txt"
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 25]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+7. Responses from the Server to the Client
+
+ The server responds to the client using one of a few response
+ packets. All requests can return a SSH_FXP_STATUS response upon
+ failure. When the operation is successful, any of the responses may
+ be returned (depending on the operation). If no data needs to be
+ returned to the client, the SSH_FXP_STATUS response with SSH_FX_OK
+ status is appropriate. Otherwise, the SSH_FXP_HANDLE message is used
+ to return a file handle (for SSH_FXP_OPEN and SSH_FXP_OPENDIR
+ requests), SSH_FXP_DATA is used to return data from SSH_FXP_READ,
+ SSH_FXP_NAME is used to return one or more file names from a
+ SSH_FXP_READDIR or SSH_FXP_REALPATH request, and SSH_FXP_ATTRS is
+ used to return file attributes from SSH_FXP_STAT, SSH_FXP_LSTAT, and
+ SSH_FXP_FSTAT requests.
+
+ Exactly one response will be returned for each request. Each
+ response packet contains a request identifier which can be used to
+ match each response with the corresponding request. Note that it is
+ legal to have several requests outstanding simultaneously, and the
+ server is allowed to send responses to them in a different order from
+ the order in which the requests were sent (the result of their
+ execution, however, is guaranteed to be as if they had been processed
+ one at a time in the order in which the requests were sent).
+
+ Response packets are of the same general format as request packets.
+ Each response packet begins with the request identifier.
+
+ The format of the data portion of the SSH_FXP_STATUS response is as
+ follows:
+
+ uint32 id
+ uint32 error/status code
+ string error message (ISO-10646 UTF-8 [RFC-2279])
+ string language tag (as defined in [RFC-1766])
+
+ where `id' is the request identifier, and `error/status code'
+ indicates the result of the requested operation. The value SSH_FX_OK
+ indicates success, and all other values indicate failure.
+
+ Currently, the following values are defined (other values may be
+ defined by future versions of this protocol):
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 26]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ #define SSH_FX_OK 0
+ #define SSH_FX_EOF 1
+ #define SSH_FX_NO_SUCH_FILE 2
+ #define SSH_FX_PERMISSION_DENIED 3
+ #define SSH_FX_FAILURE 4
+ #define SSH_FX_BAD_MESSAGE 5
+ #define SSH_FX_NO_CONNECTION 6
+ #define SSH_FX_CONNECTION_LOST 7
+ #define SSH_FX_OP_UNSUPPORTED 8
+ #define SSH_FX_INVALID_HANDLE 9
+ #define SSH_FX_NO_SUCH_PATH 10
+ #define SSH_FX_FILE_ALREADY_EXISTS 11
+ #define SSH_FX_WRITE_PROTECT 12
+ #define SSH_FX_NO_MEDIA 13
+
+ SSH_FX_OK
+ Indicates successful completion of the operation.
+
+ SSH_FX_EOF
+ indicates end-of-file condition; for SSH_FX_READ it means that no
+ more data is available in the file, and for SSH_FX_READDIR it
+ indicates that no more files are contained in the directory.
+
+ SSH_FX_NO_SUCH_FILE
+ is returned when a reference is made to a file which does not
+ exist.
+
+ SSH_FX_PERMISSION_DENIED
+ is returned when the authenticated user does not have sufficient
+ permissions to perform the operation.
+
+ SSH_FX_FAILURE
+ is a generic catch-all error message; it should be returned if an
+ error occurs for which there is no more specific error code
+ defined.
+
+ SSH_FX_BAD_MESSAGE
+ may be returned if a badly formatted packet or protocol
+ incompatibility is detected.
+
+ SSH_FX_NO_CONNECTION
+ is a pseudo-error which indicates that the client has no
+ connection to the server (it can only be generated locally by the
+ client, and MUST NOT be returned by servers).
+
+ SSH_FX_CONNECTION_LOST
+ is a pseudo-error which indicates that the connection to the
+ server has been lost (it can only be generated locally by the
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 27]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ client, and MUST NOT be returned by servers).
+
+ SSH_FX_OP_UNSUPPORTED
+ indicates that an attempt was made to perform an operation which
+ is not supported for the server (it may be generated locally by
+ the client if e.g. the version number exchange indicates that a
+ required feature is not supported by the server, or it may be
+ returned by the server if the server does not implement an
+ operation).
+
+ SSH_FX_INVALID_HANDLE
+ The handle value was invalid.
+
+ SSH_FX_NO_SUCH_PATH
+ The file path does not exist or is invalid.
+
+ SSH_FX_FILE_ALREADY_EXISTS
+ The file already exists.
+
+ SSH_FX_WRITE_PROTECT
+ The file is on read only media, or the media is write protected.
+
+ SSH_FX_NO_MEDIA
+ The requested operation can not be completed because there is no
+ media available in the drive.
+
+ The SSH_FXP_HANDLE response has the following format:
+
+ uint32 id
+ string handle
+
+ where `id' is the request identifier, and `handle' is an arbitrary
+ string that identifies an open file or directory on the server. The
+ handle is opaque to the client; the client MUST NOT attempt to
+ interpret or modify it in any way. The length of the handle string
+ MUST NOT exceed 256 data bytes.
+
+ The SSH_FXP_DATA response has the following format:
+
+ uint32 id
+ string data
+
+ where `id' is the request identifier, and `data' is an arbitrary byte
+ string containing the requested data. The data string may be at most
+ the number of bytes requested in a SSH_FXP_READ request, but may also
+ be shorter if end of file is reached or if the read is from something
+ other than a regular file.
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 28]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ The SSH_FXP_NAME response has the following format:
+
+ uint32 id
+ uint32 count
+ repeats count times:
+ string filename [UTF-8]
+ ATTRS attrs
+
+ where `id' is the request identifier, `count' is the number of names
+ returned in this response, and the remaining fields repeat `count'
+ times (so that all three fields are first included for the first
+ file, then for the second file, etc). In the repeated part,
+ `filename' is a file name being returned (for SSH_FXP_READDIR, it
+ will be a relative name within the directory, without any path
+ components; for SSH_FXP_REALPATH it will be an absolute path name),
+ and `attrs' is the attributes of the file as described in Section
+ ``File Attributes''.
+
+ The SSH_FXP_ATTRS response has the following format:
+
+ uint32 id
+ ATTRS attrs
+
+ where `id' is the request identifier, and `attrs' is the returned
+ file attributes as described in Section ``File Attributes''.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 29]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+8. Vendor-Specific Extensions
+
+ The SSH_FXP_EXTENDED request provides a generic extension mechanism
+ for adding vendor-specific commands. The request has the following
+ format:
+
+ uint32 id
+ string extended-request
+ ... any request-specific data ...
+
+ where `id' is the request identifier, and `extended-request' is a
+ string of the format "name@domain", where domain is an internet
+ domain name of the vendor defining the request. The rest of the
+ request is completely vendor-specific, and servers should only
+ attempt to interpret it if they recognize the `extended-request'
+ name.
+
+ The server may respond to such requests using any of the response
+ packets defined in Section ``Responses from the Server to the
+ Client''. Additionally, the server may also respond with a
+ SSH_FXP_EXTENDED_REPLY packet, as defined below. If the server does
+ not recognize the `extended-request' name, then the server MUST
+ respond with SSH_FXP_STATUS with error/status set to
+ SSH_FX_OP_UNSUPPORTED.
+
+ The SSH_FXP_EXTENDED_REPLY packet can be used to carry arbitrary
+ extension-specific data from the server to the client. It is of the
+ following format:
+
+ uint32 id
+ ... any request-specific data ...
+
+ There is a range of packet types reserved for use by extensions. In
+ order to avoid collision, extensions that turn on the use of
+ additional packet types should determine those numbers dynamically.
+
+ The suggested way of doing this is have an extension request from the
+ client to the server that enables the extension; the extension
+ response from the server to the client would specify the actual type
+ values to use, in additional to any other data.
+
+ Extension authors should be mindful of the limited range of packet
+ types available (there are only 45 values available) and avoid
+ requiring a new packet type where possible.
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 30]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+9. Security Considerations
+
+ This protocol assumes that it is run over a secure channel and that
+ the endpoints of the channel have been authenticated. Thus, this
+ protocol assumes that it is externally protected from network-level
+ attacks.
+
+ This protocol provides file system access to arbitrary files on the
+ server (only constrained by the server implementation). It is the
+ responsibility of the server implementation to enforce any access
+ controls that may be required to limit the access allowed for any
+ particular user (the user being authenticated externally to this
+ protocol, typically using the SSH User Authentication Protocol [8].
+
+ Care must be taken in the server implementation to check the validity
+ of received file handle strings. The server should not rely on them
+ directly; it MUST check the validity of each handle before relying on
+ it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 31]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+10. Changes from previous protocol versions
+
+ The SSH File Transfer Protocol has changed over time, before it's
+ standardization. The following is a description of the incompatible
+ changes between different versions.
+
+10.1 Changes between versions 4 and 3
+
+ Many of the changes between version 4 and version 3 are to the
+ attribute structure to make it more flexible for non-unix platforms.
+
+ o Clarify the use of stderr by the server.
+
+ o Clarify handling of very large read requests by the server.
+
+ o Make all filenames UTF-8.
+
+ o Added 'newline' extension.
+
+ o Made time fields 64 bit, and optionally have nanosecond resultion.
+
+ o Made file attribute owner and group strings so they can actually
+ be used on disparate systems.
+
+ o Added createtime field, and added separate flags for atime,
+ createtime, and mtime so they can be set separately.
+
+ o Split the file type out of the permissions field and into it's own
+ field (which is always present.)
+
+ o Added acl attribute.
+
+ o Added SSH_FXF_TEXT file open flag.
+
+ o Added flags field to the get stat commands so that the client can
+ specifically request information the server might not normally
+ included for performance reasons.
+
+ o Removed the long filename from the names structure-- it can now be
+ built from information available in the attrs structure.
+
+ o Added reserved range of packet numbers for extensions.
+
+ o Added several additional error codes.
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 32]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+10.2 Changes between versions 3 and 2
+
+ o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.
+
+ o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were
+ added.
+
+ o The SSH_FXP_STATUS message was changed to include fields `error
+ message' and `language tag'.
+
+
+10.3 Changes between versions 2 and 1
+
+ o The SSH_FXP_RENAME message was added.
+
+
+10.4 Changes between versions 1 and 0
+
+ o Implementation changes, no actual protocol changes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 33]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+11. Trademark Issues
+
+ "ssh" is a registered trademark of SSH Communications Security Corp
+ in the United States and/or other countries.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 34]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+References
+
+ [1] Dierks, T., Allen, C., Treese, W., Karlton, P., Freier, A. and
+ P. Kocher, "The TLS Protocol Version 1.0", RFC 2246, January
+ 1999.
+
+ [2] Alvestrand, H., "IETF Policy on Character Sets and Languages",
+ BCP 18, RFC 2277, January 1998.
+
+ [3] Shepler, S., Callaghan, B., Robinson, D., Thurlow, R., Beame,
+ C., Eisler, M. and D. Noveck, "NFS version 4 Protocol", RFC
+ 3010, December 2000.
+
+ [4] Institute of Electrical and Electronics Engineers, "Information
+ Technology - Portable Operating System Interface (POSIX) - Part
+ 1: System Application Program Interface (API) [C Language]",
+ IEEE Standard 1003.2, 1996.
+
+ [5] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Protocol Architecture",
+ draft-ietf-secsh-architecture-13 (work in progress), September
+ 2002.
+
+ [6] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Protocol Transport Protocol",
+ draft-ietf-secsh-transport-15 (work in progress), September
+ 2002.
+
+ [7] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Connection Protocol", draft-ietf-secsh-connect-16
+ (work in progress), September 2002.
+
+ [8] Rinne, T., Ylonen, T., Kivinen, T., Saarinen, M. and S.
+ Lehtinen, "SSH Authentication Protocol",
+ draft-ietf-secsh-userauth-16 (work in progress), September 2002.
+
+
+Authors' Addresses
+
+ Joseph Galbraith
+ VanDyke Software
+ 4848 Tramway Ridge Blvd
+ Suite 101
+ Albuquerque, NM 87111
+ US
+
+ Phone: +1 505 332 5700
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 35]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ Tatu Ylonen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+ Sami Lehtinen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 36]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 37]
+
+Internet-Draft SSH File Transfer Protocol December 2002
+
+
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Galbraith, et al. Expires June 18, 2003 [Page 38]
+
+
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps
new file mode 100644
index 0000000000..d692285b4e
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.2.ps
@@ -0,0 +1,3205 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 75 0 595 747
+%%Title: Enscript Output
+%%For: Magnus Thoang
+%%Creator: GNU enscript 1.6.1
+%%CreationDate: Fri Oct 31 13:35:14 2003
+%%Orientation: Portrait
+%%Pages: 15 0
+%%DocumentMedia: A4 595 842 0 () ()
+%%DocumentNeededResources: (atend)
+%%EndComments
+%%BeginProlog
+%%BeginProcSet: PStoPS 1 15
+userdict begin
+[/showpage/erasepage/copypage]{dup where{pop dup load
+ type/operatortype eq{1 array cvx dup 0 3 index cvx put
+ bind def}{pop}ifelse}{pop}ifelse}forall
+[/letter/legal/executivepage/a4/a4small/b5/com10envelope
+ /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
+ /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
+ {pop{}def}ifelse}{pop}ifelse}forall
+/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
+ {pop def}ifelse}{def}ifelse
+/PStoPSmatrix matrix currentmatrix def
+/PStoPSxform matrix def/PStoPSclip{clippath}def
+/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
+/initmatrix{matrix defaultmatrix setmatrix}bind def
+/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
+ [{currentpoint}stopped{$error/newerror false put{newpath}}
+ {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
+ {[/newpath cvx{/moveto cvx}{/lineto cvx}
+ {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
+ stopped{$error/errorname get/invalidaccess eq{cleartomark
+ $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
+ /initclip dup load dup type dup/operatortype eq{pop exch pop}
+ {dup/arraytype eq exch/packedarraytype eq or
+ {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
+ {pop cvx}ifelse}ifelse
+ {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
+/initgraphics{initmatrix newpath initclip 1 setlinewidth
+ 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
+ 10 setmiterlimit}bind def
+end
+%%EndProcSet
+%%BeginResource: procset Enscript-Prolog 1.6 1
+%
+% Procedures.
+%
+
+/_S { % save current state
+ /_s save def
+} def
+/_R { % restore from saved state
+ _s restore
+} def
+
+/S { % showpage protecting gstate
+ gsave
+ showpage
+ grestore
+} bind def
+
+/MF { % fontname newfontname -> - make a new encoded font
+ /newfontname exch def
+ /fontname exch def
+
+ /fontdict fontname findfont def
+ /newfont fontdict maxlength dict def
+
+ fontdict {
+ exch
+ dup /FID eq {
+ % skip FID pair
+ pop pop
+ } {
+ % copy to the new font dictionary
+ exch newfont 3 1 roll put
+ } ifelse
+ } forall
+
+ newfont /FontName newfontname put
+
+ % insert only valid encoding vectors
+ encoding_vector length 256 eq {
+ newfont /Encoding encoding_vector put
+ } if
+
+ newfontname newfont definefont pop
+} def
+
+/SF { % fontname width height -> - set a new font
+ /height exch def
+ /width exch def
+
+ findfont
+ [width 0 0 height 0 0] makefont setfont
+} def
+
+/SUF { % fontname width height -> - set a new user font
+ /height exch def
+ /width exch def
+
+ /F-gs-user-font MF
+ /F-gs-user-font width height SF
+} def
+
+/M {moveto} bind def
+/s {show} bind def
+
+/Box { % x y w h -> - define box path
+ /d_h exch def /d_w exch def /d_y exch def /d_x exch def
+ d_x d_y moveto
+ d_w 0 rlineto
+ 0 d_h rlineto
+ d_w neg 0 rlineto
+ closepath
+} def
+
+/bgs { % x y height blskip gray str -> - show string with bg color
+ /str exch def
+ /gray exch def
+ /blskip exch def
+ /height exch def
+ /y exch def
+ /x exch def
+
+ gsave
+ x y blskip sub str stringwidth pop height Box
+ gray setgray
+ fill
+ grestore
+ x y M str s
+} def
+
+% Highlight bars.
+/highlight_bars { % nlines lineheight output_y_margin gray -> -
+ gsave
+ setgray
+ /ymarg exch def
+ /lineheight exch def
+ /nlines exch def
+
+ % This 2 is just a magic number to sync highlight lines to text.
+ 0 d_header_y ymarg sub 2 sub translate
+
+ /cw d_output_w cols div def
+ /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
+
+ % for each column
+ 0 1 cols 1 sub {
+ cw mul /xp exch def
+
+ % for each rows
+ 0 1 nrows 1 sub {
+ /rn exch def
+ rn lineheight mul neg /yp exch def
+ rn nlines idiv 2 mod 0 eq {
+ % Draw highlight bar. 4 is just a magic indentation.
+ xp 4 add yp cw 8 sub lineheight neg Box fill
+ } if
+ } for
+ } for
+
+ grestore
+} def
+
+% Line highlight bar.
+/line_highlight { % x y width height gray -> -
+ gsave
+ /gray exch def
+ Box gray setgray fill
+ grestore
+} def
+
+% Column separator lines.
+/column_lines {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h translate
+ /cw d_output_w cols div def
+ 1 1 cols 1 sub {
+ cw mul 0 moveto
+ 0 d_output_h rlineto stroke
+ } for
+ grestore
+} def
+
+% Column borders.
+/column_borders {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h moveto
+ 0 d_output_h rlineto
+ d_output_w 0 rlineto
+ 0 d_output_h neg rlineto
+ closepath stroke
+ grestore
+} def
+
+% Do the actual underlay drawing
+/draw_underlay {
+ ul_style 0 eq {
+ ul_str true charpath stroke
+ } {
+ ul_str show
+ } ifelse
+} def
+
+% Underlay
+/underlay { % - -> -
+ gsave
+ 0 d_page_h translate
+ d_page_h neg d_page_w atan rotate
+
+ ul_gray setgray
+ ul_font setfont
+ /dw d_page_h dup mul d_page_w dup mul add sqrt def
+ ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
+ draw_underlay
+ grestore
+} def
+
+/user_underlay { % - -> -
+ gsave
+ ul_x ul_y translate
+ ul_angle rotate
+ ul_gray setgray
+ ul_font setfont
+ 0 0 ul_h_ptsize 2 div sub moveto
+ draw_underlay
+ grestore
+} def
+
+% Page prefeed
+/page_prefeed { % bool -> -
+ statusdict /prefeed known {
+ statusdict exch /prefeed exch put
+ } {
+ pop
+ } ifelse
+} def
+
+% Wrapped line markers
+/wrapped_line_mark { % x y charwith charheight type -> -
+ /type exch def
+ /h exch def
+ /w exch def
+ /y exch def
+ /x exch def
+
+ type 2 eq {
+ % Black boxes (like TeX does)
+ gsave
+ 0 setlinewidth
+ x w 4 div add y M
+ 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
+ closepath fill
+ grestore
+ } {
+ type 3 eq {
+ % Small arrows
+ gsave
+ .2 setlinewidth
+ x w 2 div add y h 2 div add M
+ w 4 div 0 rlineto
+ x w 4 div add y lineto stroke
+
+ x w 4 div add w 8 div add y h 4 div add M
+ x w 4 div add y lineto
+ w 4 div h 8 div rlineto stroke
+ grestore
+ } {
+ % do nothing
+ } ifelse
+ } ifelse
+} def
+
+% EPSF import.
+
+/BeginEPSF {
+ /b4_Inc_state save def % Save state for cleanup
+ /dict_count countdictstack def % Count objects on dict stack
+ /op_count count 1 sub def % Count objects on operand stack
+ userdict begin
+ /showpage { } def
+ 0 setgray 0 setlinecap
+ 1 setlinewidth 0 setlinejoin
+ 10 setmiterlimit [ ] 0 setdash newpath
+ /languagelevel where {
+ pop languagelevel
+ 1 ne {
+ false setstrokeadjust false setoverprint
+ } if
+ } if
+} bind def
+
+/EndEPSF {
+ count op_count sub { pos } repeat % Clean up stacks
+ countdictstack dict_count sub { end } repeat
+ b4_Inc_state restore
+} bind def
+
+% Check PostScript language level.
+/languagelevel where {
+ pop /gs_languagelevel languagelevel def
+} {
+ /gs_languagelevel 1 def
+} ifelse
+%%EndResource
+%%BeginResource: procset Enscript-Encoding-88591 1.6 1
+/encoding_vector [
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclam /quotedbl /numbersign
+/dollar /percent /ampersand /quoteright
+/parenleft /parenright /asterisk /plus
+/comma /hyphen /period /slash
+/zero /one /two /three
+/four /five /six /seven
+/eight /nine /colon /semicolon
+/less /equal /greater /question
+/at /A /B /C
+/D /E /F /G
+/H /I /J /K
+/L /M /N /O
+/P /Q /R /S
+/T /U /V /W
+/X /Y /Z /bracketleft
+/backslash /bracketright /asciicircum /underscore
+/quoteleft /a /b /c
+/d /e /f /g
+/h /i /j /k
+/l /m /n /o
+/p /q /r /s
+/t /u /v /w
+/x /y /z /braceleft
+/bar /braceright /tilde /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclamdown /cent /sterling
+/currency /yen /brokenbar /section
+/dieresis /copyright /ordfeminine /guillemotleft
+/logicalnot /hyphen /registered /macron
+/degree /plusminus /twosuperior /threesuperior
+/acute /mu /paragraph /bullet
+/cedilla /onesuperior /ordmasculine /guillemotright
+/onequarter /onehalf /threequarters /questiondown
+/Agrave /Aacute /Acircumflex /Atilde
+/Adieresis /Aring /AE /Ccedilla
+/Egrave /Eacute /Ecircumflex /Edieresis
+/Igrave /Iacute /Icircumflex /Idieresis
+/Eth /Ntilde /Ograve /Oacute
+/Ocircumflex /Otilde /Odieresis /multiply
+/Oslash /Ugrave /Uacute /Ucircumflex
+/Udieresis /Yacute /Thorn /germandbls
+/agrave /aacute /acircumflex /atilde
+/adieresis /aring /ae /ccedilla
+/egrave /eacute /ecircumflex /edieresis
+/igrave /iacute /icircumflex /idieresis
+/eth /ntilde /ograve /oacute
+/ocircumflex /otilde /odieresis /divide
+/oslash /ugrave /uacute /ucircumflex
+/udieresis /yacute /thorn /ydieresis
+] def
+%%EndResource
+%%EndProlog
+%%BeginSetup
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier
+/HFpt_w 10 def
+/HFpt_h 10 def
+/Courier-Bold /HF-gs-font MF
+/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
+/Courier /F-gs-font MF
+/F-gs-font 10 10 SF
+/#copies 1 def
+/d_page_w 520 def
+/d_page_h 747 def
+/d_header_x 0 def
+/d_header_y 747 def
+/d_header_w 520 def
+/d_header_h 0 def
+/d_footer_x 0 def
+/d_footer_y 0 def
+/d_footer_w 520 def
+/d_footer_h 0 def
+/d_output_w 520 def
+/d_output_h 747 def
+/cols 1 def
+userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
+ matrix invertmatrix matrix concatmatrix
+ matrix invertmatrix put
+%%EndSetup
+%%Page: (0,1) 1
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 1 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 701 M
+(Network Working Group T. Ylonen) s
+5 690 M
+(Internet-Draft SSH Communications Security Corp) s
+5 679 M
+(Expires: March 31, 2004 D. Moffat, Editor, Ed.) s
+5 668 M
+( Sun Microsystems, Inc) s
+5 657 M
+( Oct 2003) s
+5 624 M
+( SSH Transport Layer Protocol) s
+5 613 M
+( draft-ietf-secsh-transport-17.txt) s
+5 591 M
+(Status of this Memo) s
+5 569 M
+( This document is an Internet-Draft and is in full conformance with) s
+5 558 M
+( all provisions of Section 10 of RFC2026.) s
+5 536 M
+( Internet-Drafts are working documents of the Internet Engineering) s
+5 525 M
+( Task Force \(IETF\), its areas, and its working groups. Note that other) s
+5 514 M
+( groups may also distribute working documents as Internet-Drafts.) s
+5 492 M
+( Internet-Drafts are draft documents valid for a maximum of six months) s
+5 481 M
+( and may be updated, replaced, or obsoleted by other documents at any) s
+5 470 M
+( time. It is inappropriate to use Internet-Drafts as reference) s
+5 459 M
+( material or to cite them other than as "work in progress.") s
+5 437 M
+( The list of current Internet-Drafts can be accessed at http://) s
+5 426 M
+( www.ietf.org/ietf/1id-abstracts.txt.) s
+5 404 M
+( The list of Internet-Draft Shadow Directories can be accessed at) s
+5 393 M
+( http://www.ietf.org/shadow.html.) s
+5 371 M
+( This Internet-Draft will expire on March 31, 2004.) s
+5 349 M
+(Copyright Notice) s
+5 327 M
+( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
+5 305 M
+(Abstract) s
+5 283 M
+( SSH is a protocol for secure remote login and other secure network) s
+5 272 M
+( services over an insecure network.) s
+5 250 M
+( This document describes the SSH transport layer protocol which) s
+5 239 M
+( typically runs on top of TCP/IP. The protocol can be used as a basis) s
+5 228 M
+( for a number of secure network services. It provides strong) s
+5 217 M
+( encryption, server authentication, and integrity protection. It may) s
+5 206 M
+( also provide compression.) s
+5 184 M
+( Key exchange method, public key algorithm, symmetric encryption) s
+5 173 M
+( algorithm, message authentication algorithm, and hash algorithm are) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 2 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( all negotiated.) s
+5 668 M
+( This document also describes the Diffie-Hellman key exchange method) s
+5 657 M
+( and the minimal set of algorithms that are needed to implement the) s
+5 646 M
+( SSH transport layer protocol.) s
+5 624 M
+(Table of Contents) s
+5 602 M
+( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 591 M
+( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 580 M
+( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s
+5 569 M
+( 4. Connection Setup . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 558 M
+( 4.1 Use over TCP/IP . . . . . . . . . . . . . . . . . . . . . . 4) s
+5 547 M
+( 4.2 Protocol Version Exchange . . . . . . . . . . . . . . . . . 4) s
+5 536 M
+( 4.3 Compatibility With Old SSH Versions . . . . . . . . . . . . 4) s
+5 525 M
+( 4.3.1 Old Client, New Server . . . . . . . . . . . . . . . . . . . 5) s
+5 514 M
+( 4.3.2 New Client, Old Server . . . . . . . . . . . . . . . . . . . 5) s
+5 503 M
+( 5. Binary Packet Protocol . . . . . . . . . . . . . . . . . . . 5) s
+5 492 M
+( 5.1 Maximum Packet Length . . . . . . . . . . . . . . . . . . . 6) s
+5 481 M
+( 5.2 Compression . . . . . . . . . . . . . . . . . . . . . . . . 7) s
+5 470 M
+( 5.3 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . 7) s
+5 459 M
+( 5.4 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 9) s
+5 448 M
+( 5.5 Key Exchange Methods . . . . . . . . . . . . . . . . . . . . 10) s
+5 437 M
+( 5.6 Public Key Algorithms . . . . . . . . . . . . . . . . . . . 11) s
+5 426 M
+( 6. Key Exchange . . . . . . . . . . . . . . . . . . . . . . . . 13) s
+5 415 M
+( 6.1 Algorithm Negotiation . . . . . . . . . . . . . . . . . . . 13) s
+5 404 M
+( 6.2 Output from Key Exchange . . . . . . . . . . . . . . . . . . 16) s
+5 393 M
+( 6.3 Taking Keys Into Use . . . . . . . . . . . . . . . . . . . . 17) s
+5 382 M
+( 7. Diffie-Hellman Key Exchange . . . . . . . . . . . . . . . . 18) s
+5 371 M
+( 7.1 diffie-hellman-group1-sha1 . . . . . . . . . . . . . . . . . 19) s
+5 360 M
+( 8. Key Re-Exchange . . . . . . . . . . . . . . . . . . . . . . 20) s
+5 349 M
+( 9. Service Request . . . . . . . . . . . . . . . . . . . . . . 21) s
+5 338 M
+( 10. Additional Messages . . . . . . . . . . . . . . . . . . . . 21) s
+5 327 M
+( 10.1 Disconnection Message . . . . . . . . . . . . . . . . . . . 22) s
+5 316 M
+( 10.2 Ignored Data Message . . . . . . . . . . . . . . . . . . . . 22) s
+5 305 M
+( 10.3 Debug Message . . . . . . . . . . . . . . . . . . . . . . . 23) s
+5 294 M
+( 10.4 Reserved Messages . . . . . . . . . . . . . . . . . . . . . 23) s
+5 283 M
+( 11. Summary of Message Numbers . . . . . . . . . . . . . . . . . 23) s
+5 272 M
+( 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 24) s
+5 261 M
+( 13. Security Considerations . . . . . . . . . . . . . . . . . . 24) s
+5 250 M
+( 14. Intellectual Property . . . . . . . . . . . . . . . . . . . 24) s
+5 239 M
+( 15. Additional Information . . . . . . . . . . . . . . . . . . . 24) s
+5 228 M
+( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 26) s
+5 217 M
+( Normative . . . . . . . . . . . . . . . . . . . . . . . . . 25) s
+5 206 M
+( Informative . . . . . . . . . . . . . . . . . . . . . . . . 25) s
+5 195 M
+( A. Contibutors . . . . . . . . . . . . . . . . . . . . . . . . 27) s
+5 184 M
+( Intellectual Property and Copyright Statements . . . . . . . 28) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (2,3) 2
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 3 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+(1. Contributors) s
+5 668 M
+( The major original contributors of this document were: Tatu Ylonen,) s
+5 657 M
+( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
+5 646 M
+( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
+5 635 M
+( Jyvaskyla\)) s
+5 613 M
+( The document editor is: [email protected]. Comments on this) s
+5 602 M
+( internet draft should be sent to the IETF SECSH working group,) s
+5 591 M
+( details at: http://ietf.org/html.charters/secsh-charter.html) s
+5 569 M
+(2. Introduction) s
+5 547 M
+( The SSH transport layer is a secure low level transport protocol. It) s
+5 536 M
+( provides strong encryption, cryptographic host authentication, and) s
+5 525 M
+( integrity protection.) s
+5 503 M
+( Authentication in this protocol level is host-based; this protocol) s
+5 492 M
+( does not perform user authentication. A higher level protocol for) s
+5 481 M
+( user authentication can be designed on top of this protocol.) s
+5 459 M
+( The protocol has been designed to be simple, flexible, to allow) s
+5 448 M
+( parameter negotiation, and to minimize the number of round-trips.) s
+5 437 M
+( Key exchange method, public key algorithm, symmetric encryption) s
+5 426 M
+( algorithm, message authentication algorithm, and hash algorithm are) s
+5 415 M
+( all negotiated. It is expected that in most environments, only 2) s
+5 404 M
+( round-trips will be needed for full key exchange, server) s
+5 393 M
+( authentication, service request, and acceptance notification of) s
+5 382 M
+( service request. The worst case is 3 round-trips.) s
+5 360 M
+(3. Conventions Used in This Document) s
+5 338 M
+( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s
+5 327 M
+( and "MAY" that appear in this document are to be interpreted as) s
+5 316 M
+( described in [RFC2119].) s
+5 294 M
+( The used data types and terminology are specified in the architecture) s
+5 283 M
+( document [SSH-ARCH].) s
+5 261 M
+( The architecture document also discusses the algorithm naming) s
+5 250 M
+( conventions that MUST be used with the SSH protocols.) s
+5 228 M
+(4. Connection Setup) s
+5 206 M
+( SSH works over any 8-bit clean, binary-transparent transport. The) s
+5 195 M
+( underlying transport SHOULD protect against transmission errors as) s
+5 184 M
+( such errors cause the SSH connection to terminate.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 4 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( The client initiates the connection.) s
+5 668 M
+(4.1 Use over TCP/IP) s
+5 646 M
+( When used over TCP/IP, the server normally listens for connections on) s
+5 635 M
+( port 22. This port number has been registered with the IANA, and has) s
+5 624 M
+( been officially assigned for SSH.) s
+5 602 M
+(4.2 Protocol Version Exchange) s
+5 580 M
+( When the connection has been established, both sides MUST send an) s
+5 569 M
+( identification string of the form "SSH-protoversion-softwareversion) s
+5 558 M
+( comments", followed by carriage return and newline characters \(ASCII) s
+5 547 M
+( 13 and 10, respectively\). Both sides MUST be able to process) s
+5 536 M
+( identification strings without carriage return character. No null) s
+5 525 M
+( character is sent. The maximum length of the string is 255) s
+5 514 M
+( characters, including the carriage return and newline.) s
+5 492 M
+( The part of the identification string preceding carriage return and) s
+5 481 M
+( newline is used in the Diffie-Hellman key exchange \(see Section) s
+5 470 M
+( Section 7\).) s
+5 448 M
+( The server MAY send other lines of data before sending the version) s
+5 437 M
+( string. Each line SHOULD be terminated by a carriage return and) s
+5 426 M
+( newline. Such lines MUST NOT begin with "SSH-", and SHOULD be) s
+5 415 M
+( encoded in ISO-10646 UTF-8 [RFC2279] \(language is not specified\).) s
+5 404 M
+( Clients MUST be able to process such lines; they MAY be silently) s
+5 393 M
+( ignored, or MAY be displayed to the client user; if they are) s
+5 382 M
+( displayed, control character filtering discussed in [SSH-ARCH] SHOULD) s
+5 371 M
+( be used. The primary use of this feature is to allow TCP-wrappers to) s
+5 360 M
+( display an error message before disconnecting.) s
+5 338 M
+( Version strings MUST consist of printable US-ASCII characters, not) s
+5 327 M
+( including whitespaces or a minus sign \(-\). The version string is) s
+5 316 M
+( primarily used to trigger compatibility extensions and to indicate) s
+5 305 M
+( the capabilities of an implementation. The comment string should) s
+5 294 M
+( contain additional information that might be useful in solving user) s
+5 283 M
+( problems.) s
+5 261 M
+( The protocol version described in this document is 2.0.) s
+5 239 M
+( Key exchange will begin immediately after sending this identifier.) s
+5 228 M
+( All packets following the identification string SHALL use the binary) s
+5 217 M
+( packet protocol, to be described below.) s
+5 195 M
+(4.3 Compatibility With Old SSH Versions) s
+5 173 M
+( During the transition period, it is important to be able to work in a) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (4,5) 3
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 5 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( way that is compatible with the installed SSH clients and servers) s
+5 679 M
+( that use an older version of the protocol. Information in this) s
+5 668 M
+( section is only relevant for implementations supporting compatibility) s
+5 657 M
+( with SSH versions 1.x. There is no standards track or informational) s
+5 646 M
+( draft available that defines the SSH 1.x protocol. The only known) s
+5 635 M
+( documentation of the 1.x protocol is contained in README files that) s
+5 624 M
+( are shipped along with the source code.) s
+5 602 M
+(4.3.1 Old Client, New Server) s
+5 580 M
+( Server implementations MAY support a configurable "compatibility") s
+5 569 M
+( flag that enables compatibility with old versions. When this flag is) s
+5 558 M
+( on, the server SHOULD identify its protocol version as "1.99".) s
+5 547 M
+( Clients using protocol 2.0 MUST be able to identify this as identical) s
+5 536 M
+( to "2.0". In this mode the server SHOULD NOT send the carriage) s
+5 525 M
+( return character \(ASCII 13\) after the version identification string.) s
+5 503 M
+( In the compatibility mode the server SHOULD NOT send any further data) s
+5 492 M
+( after its initialization string until it has received an) s
+5 481 M
+( identification string from the client. The server can then determine) s
+5 470 M
+( whether the client is using an old protocol, and can revert to the) s
+5 459 M
+( old protocol if required. In the compatibility mode, the server MUST) s
+5 448 M
+( NOT send additional data before the version string.) s
+5 426 M
+( When compatibility with old clients is not needed, the server MAY) s
+5 415 M
+( send its initial key exchange data immediately after the) s
+5 404 M
+( identification string.) s
+5 382 M
+(4.3.2 New Client, Old Server) s
+5 360 M
+( Since the new client MAY immediately send additional data after its) s
+5 349 M
+( identification string \(before receiving server's identification\), the) s
+5 338 M
+( old protocol may already have been corrupted when the client learns) s
+5 327 M
+( that the server is old. When this happens, the client SHOULD close) s
+5 316 M
+( the connection to the server, and reconnect using the old protocol.) s
+5 294 M
+(5. Binary Packet Protocol) s
+5 272 M
+( Each packet is in the following format:) s
+5 250 M
+( uint32 packet_length) s
+5 239 M
+( byte padding_length) s
+5 228 M
+( byte[n1] payload; n1 = packet_length - padding_length - 1) s
+5 217 M
+( byte[n2] random padding; n2 = padding_length) s
+5 206 M
+( byte[m] mac \(message authentication code\); m = mac_length) s
+5 184 M
+( packet_length) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 6 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( The length of the packet \(bytes\), not including MAC or the) s
+5 679 M
+( packet_length field itself.) s
+5 657 M
+( padding_length) s
+5 646 M
+( Length of padding \(bytes\).) s
+5 624 M
+( payload) s
+5 613 M
+( The useful contents of the packet. If compression has been) s
+5 602 M
+( negotiated, this field is compressed. Initially, compression) s
+5 591 M
+( MUST be "none".) s
+5 569 M
+( random padding) s
+5 558 M
+( Arbitrary-length padding, such that the total length of) s
+5 547 M
+( \(packet_length || padding_length || payload || padding\) is a) s
+5 536 M
+( multiple of the cipher block size or 8, whichever is larger.) s
+5 525 M
+( There MUST be at least four bytes of padding. The padding) s
+5 514 M
+( SHOULD consist of random bytes. The maximum amount of padding) s
+5 503 M
+( is 255 bytes.) s
+5 481 M
+( mac) s
+5 470 M
+( Message authentication code. If message authentication has) s
+5 459 M
+( been negotiated, this field contains the MAC bytes. Initially,) s
+5 448 M
+( the MAC algorithm MUST be "none".) s
+5 415 M
+( Note that length of the concatenation of packet length, padding) s
+5 404 M
+( length, payload, and padding MUST be a multiple of the cipher block) s
+5 393 M
+( size or 8, whichever is larger. This constraint MUST be enforced) s
+5 382 M
+( even when using stream ciphers. Note that the packet length field is) s
+5 371 M
+( also encrypted, and processing it requires special care when sending) s
+5 360 M
+( or receiving packets.) s
+5 338 M
+( The minimum size of a packet is 16 \(or the cipher block size,) s
+5 327 M
+( whichever is larger\) bytes \(plus MAC\); implementations SHOULD decrypt) s
+5 316 M
+( the length after receiving the first 8 \(or cipher block size,) s
+5 305 M
+( whichever is larger\) bytes of a packet.) s
+5 283 M
+(5.1 Maximum Packet Length) s
+5 261 M
+( All implementations MUST be able to process packets with uncompressed) s
+5 250 M
+( payload length of 32768 bytes or less and total packet size of 35000) s
+5 239 M
+( bytes or less \(including length, padding length, payload, padding,) s
+5 228 M
+( and MAC.\). The maximum of 35000 bytes is an arbitrary chosen value) s
+5 217 M
+( larger than uncompressed size. Implementations SHOULD support longer) s
+5 206 M
+( packets, where they might be needed, e.g. if an implementation wants) s
+5 195 M
+( to send a very large number of certificates. Such packets MAY be) s
+5 184 M
+( sent if the version string indicates that the other party is able to) s
+5 173 M
+( process them. However, implementations SHOULD check that the packet) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (6,7) 4
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 7 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( length is reasonable for the implementation to avoid) s
+5 679 M
+( denial-of-service and/or buffer overflow attacks.) s
+5 657 M
+(5.2 Compression) s
+5 635 M
+( If compression has been negotiated, the payload field \(and only it\)) s
+5 624 M
+( will be compressed using the negotiated algorithm. The length field) s
+5 613 M
+( and MAC will be computed from the compressed payload. Encryption will) s
+5 602 M
+( be done after compression.) s
+5 580 M
+( Compression MAY be stateful, depending on the method. Compression) s
+5 569 M
+( MUST be independent for each direction, and implementations MUST) s
+5 558 M
+( allow independently choosing the algorithm for each direction.) s
+5 536 M
+( The following compression methods are currently defined:) s
+5 514 M
+( none REQUIRED no compression) s
+5 503 M
+( zlib OPTIONAL ZLIB \(LZ77\) compression) s
+5 481 M
+( The "zlib" compression is described in [RFC1950] and in [RFC1951].) s
+5 470 M
+( The compression context is initialized after each key exchange, and) s
+5 459 M
+( is passed from one packet to the next with only a partial flush being) s
+5 448 M
+( performed at the end of each packet. A partial flush means that the) s
+5 437 M
+( current compressed block is ended and all data will be output. If the) s
+5 426 M
+( current block is not a stored block, one or more empty blocks are) s
+5 415 M
+( added after the current block to ensure that there are at least 8) s
+5 404 M
+( bits counting from the start of the end-of-block code of the current) s
+5 393 M
+( block to the end of the packet payload.) s
+5 371 M
+( Additional methods may be defined as specified in [SSH-ARCH].) s
+5 349 M
+(5.3 Encryption) s
+5 327 M
+( An encryption algorithm and a key will be negotiated during the key) s
+5 316 M
+( exchange. When encryption is in effect, the packet length, padding) s
+5 305 M
+( length, payload and padding fields of each packet MUST be encrypted) s
+5 294 M
+( with the given algorithm.) s
+5 272 M
+( The encrypted data in all packets sent in one direction SHOULD be) s
+5 261 M
+( considered a single data stream. For example, initialization vectors) s
+5 250 M
+( SHOULD be passed from the end of one packet to the beginning of the) s
+5 239 M
+( next packet. All ciphers SHOULD use keys with an effective key length) s
+5 228 M
+( of 128 bits or more.) s
+5 206 M
+( The ciphers in each direction MUST run independently of each other,) s
+5 195 M
+( and implementations MUST allow independently choosing the algorithm) s
+5 184 M
+( for each direction \(if multiple algorithms are allowed by local) s
+5 173 M
+( policy\).) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 8 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( The following ciphers are currently defined:) s
+5 668 M
+( 3des-cbc REQUIRED three-key 3DES in CBC mode) s
+5 657 M
+( blowfish-cbc OPTIONALi Blowfish in CBC mode) s
+5 646 M
+( twofish256-cbc OPTIONAL Twofish in CBC mode,) s
+5 635 M
+( with 256-bit key) s
+5 624 M
+( twofish-cbc OPTIONAL alias for "twofish256-cbc" \(this) s
+5 613 M
+( is being retained for) s
+5 602 M
+( historical reasons\)) s
+5 591 M
+( twofish192-cbc OPTIONAL Twofish with 192-bit key) s
+5 580 M
+( twofish128-cbc OPTIONAL Twofish with 128-bit key) s
+5 569 M
+( aes256-cbc OPTIONAL AES \(Rijndael\) in CBC mode,) s
+5 558 M
+( with 256-bit key) s
+5 547 M
+( aes192-cbc OPTIONAL AES with 192-bit key) s
+5 536 M
+( aes128-cbc RECOMMENDED AES with 128-bit key) s
+5 525 M
+( serpent256-cbc OPTIONAL Serpent in CBC mode, with) s
+5 514 M
+( 256-bit key) s
+5 503 M
+( serpent192-cbc OPTIONAL Serpent with 192-bit key) s
+5 492 M
+( serpent128-cbc OPTIONAL Serpent with 128-bit key) s
+5 481 M
+( arcfour OPTIONAL the ARCFOUR stream cipher) s
+5 470 M
+( idea-cbc OPTIONAL IDEA in CBC mode) s
+5 459 M
+( cast128-cbc OPTIONAL CAST-128 in CBC mode) s
+5 448 M
+( none OPTIONAL no encryption; NOT RECOMMENDED) s
+5 426 M
+( The "3des-cbc" cipher is three-key triple-DES) s
+5 415 M
+( \(encrypt-decrypt-encrypt\), where the first 8 bytes of the key are) s
+5 404 M
+( used for the first encryption, the next 8 bytes for the decryption,) s
+5 393 M
+( and the following 8 bytes for the final encryption. This requires 24) s
+5 382 M
+( bytes of key data \(of which 168 bits are actually used\). To) s
+5 371 M
+( implement CBC mode, outer chaining MUST be used \(i.e., there is only) s
+5 360 M
+( one initialization vector\). This is a block cipher with 8 byte) s
+5 349 M
+( blocks. This algorithm is defined in [FIPS-46-3]) s
+5 327 M
+( The "blowfish-cbc" cipher is Blowfish in CBC mode, with 128 bit keys) s
+5 316 M
+( [SCHNEIER]. This is a block cipher with 8 byte blocks.) s
+5 294 M
+( The "twofish-cbc" or "twofish256-cbc" cipher is Twofish in CBC mode,) s
+5 283 M
+( with 256 bit keys as described [TWOFISH]. This is a block cipher with) s
+5 272 M
+( 16 byte blocks.) s
+5 250 M
+( The "twofish192-cbc" cipher. Same as above but with 192-bit key.) s
+5 228 M
+( The "twofish128-cbc" cipher. Same as above but with 128-bit key.) s
+5 206 M
+( The "aes256-cbc" cipher is AES \(Advanced Encryption Standard\)) s
+5 195 M
+( [FIPS-197], formerly Rijndael, in CBC mode. This version uses 256-bit) s
+5 184 M
+( key.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (8,9) 5
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 9 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( The "aes192-cbc" cipher. Same as above but with 192-bit key.) s
+5 668 M
+( The "aes128-cbc" cipher. Same as above but with 128-bit key.) s
+5 646 M
+( The "serpent256-cbc" cipher in CBC mode, with 256-bit key as) s
+5 635 M
+( described in the Serpent AES submission.) s
+5 613 M
+( The "serpent192-cbc" cipher. Same as above but with 192-bit key.) s
+5 591 M
+( The "serpent128-cbc" cipher. Same as above but with 128-bit key.) s
+5 569 M
+( The "arcfour" is the Arcfour stream cipher with 128 bit keys. The) s
+5 558 M
+( Arcfour cipher is believed to be compatible with the RC4 cipher) s
+5 547 M
+( [SCHNEIER]. RC4 is a registered trademark of RSA Data Security Inc.) s
+5 536 M
+( Arcfour \(and RC4\) has problems with weak keys, and should be used) s
+5 525 M
+( with caution.) s
+5 503 M
+( The "idea-cbc" cipher is the IDEA cipher in CBC mode [SCHNEIER].) s
+5 481 M
+( The "cast128-cbc" cipher is the CAST-128 cipher in CBC mode) s
+5 470 M
+( [RFC2144].) s
+5 448 M
+( The "none" algorithm specifies that no encryption is to be done.) s
+5 437 M
+( Note that this method provides no confidentiality protection, and it) s
+5 426 M
+( is not recommended. Some functionality \(e.g. password) s
+5 415 M
+( authentication\) may be disabled for security reasons if this cipher) s
+5 404 M
+( is chosen.) s
+5 382 M
+( Additional methods may be defined as specified in [SSH-ARCH].) s
+5 360 M
+(5.4 Data Integrity) s
+5 338 M
+( Data integrity is protected by including with each packet a message) s
+5 327 M
+( authentication code \(MAC\) that is computed from a shared secret,) s
+5 316 M
+( packet sequence number, and the contents of the packet.) s
+5 294 M
+( The message authentication algorithm and key are negotiated during) s
+5 283 M
+( key exchange. Initially, no MAC will be in effect, and its length) s
+5 272 M
+( MUST be zero. After key exchange, the selected MAC will be computed) s
+5 261 M
+( before encryption from the concatenation of packet data:) s
+5 239 M
+( mac = MAC\(key, sequence_number || unencrypted_packet\)) s
+5 217 M
+( where unencrypted_packet is the entire packet without MAC \(the length) s
+5 206 M
+( fields, payload and padding\), and sequence_number is an implicit) s
+5 195 M
+( packet sequence number represented as uint32. The sequence number is) s
+5 184 M
+( initialized to zero for the first packet, and is incremented after) s
+5 173 M
+( every packet \(regardless of whether encryption or MAC is in use\). It) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 10 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( is never reset, even if keys/algorithms are renegotiated later. It) s
+5 679 M
+( wraps around to zero after every 2^32 packets. The packet sequence) s
+5 668 M
+( number itself is not included in the packet sent over the wire.) s
+5 646 M
+( The MAC algorithms for each direction MUST run independently, and) s
+5 635 M
+( implementations MUST allow choosing the algorithm independently for) s
+5 624 M
+( both directions.) s
+5 602 M
+( The MAC bytes resulting from the MAC algorithm MUST be transmitted) s
+5 591 M
+( without encryption as the last part of the packet. The number of MAC) s
+5 580 M
+( bytes depends on the algorithm chosen.) s
+5 558 M
+( The following MAC algorithms are currently defined:) s
+5 536 M
+( hmac-sha1 REQUIRED HMAC-SHA1 \(digest length = key) s
+5 525 M
+( length = 20\)) s
+5 514 M
+( hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 \(digest) s
+5 503 M
+( length = 12, key length = 20\)) s
+5 492 M
+( hmac-md5 OPTIONAL HMAC-MD5 \(digest length = key) s
+5 481 M
+( length = 16\)) s
+5 470 M
+( hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 \(digest) s
+5 459 M
+( length = 12, key length = 16\)) s
+5 448 M
+( none OPTIONAL no MAC; NOT RECOMMENDED) s
+5 426 M
+( Figure 1) s
+5 404 M
+( The "hmac-*" algorithms are described in [RFC2104] The "*-n" MACs use) s
+5 393 M
+( only the first n bits of the resulting value.) s
+5 371 M
+( The hash algorithms are described in [SCHNEIER].) s
+5 349 M
+( Additional methods may be defined as specified in [SSH-ARCH].) s
+5 327 M
+(5.5 Key Exchange Methods) s
+5 305 M
+( The key exchange method specifies how one-time session keys are) s
+5 294 M
+( generated for encryption and for authentication, and how the server) s
+5 283 M
+( authentication is done.) s
+5 261 M
+( Only one REQUIRED key exchange method has been defined:) s
+5 239 M
+( diffie-hellman-group1-sha1 REQUIRED) s
+5 217 M
+( This method is described later in this document.) s
+5 195 M
+( Additional methods may be defined as specified in [SSH-ARCH].) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (10,11) 6
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 11 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+(5.6 Public Key Algorithms) s
+5 668 M
+( This protocol has been designed to be able to operate with almost any) s
+5 657 M
+( public key format, encoding, and algorithm \(signature and/or) s
+5 646 M
+( encryption\).) s
+5 624 M
+( There are several aspects that define a public key type:) s
+5 613 M
+( o Key format: how is the key encoded and how are certificates) s
+5 602 M
+( represented. The key blobs in this protocol MAY contain) s
+5 591 M
+( certificates in addition to keys.) s
+5 580 M
+( o Signature and/or encryption algorithms. Some key types may not) s
+5 569 M
+( support both signing and encryption. Key usage may also be) s
+5 558 M
+( restricted by policy statements in e.g. certificates. In this) s
+5 547 M
+( case, different key types SHOULD be defined for the different) s
+5 536 M
+( policy alternatives.) s
+5 525 M
+( o Encoding of signatures and/or encrypted data. This includes but is) s
+5 514 M
+( not limited to padding, byte order, and data formats.) s
+5 492 M
+( The following public key and/or certificate formats are currently defined:) s
+5 470 M
+( ssh-dss REQUIRED sign Raw DSS Key) s
+5 459 M
+( ssh-rsa RECOMMENDED sign Raw RSA Key) s
+5 448 M
+( x509v3-sign-rsa OPTIONAL sign X.509 certificates \(RSA key\)) s
+5 437 M
+( x509v3-sign-dss OPTIONAL sign X.509 certificates \(DSS key\)) s
+5 426 M
+( spki-sign-rsa OPTIONAL sign SPKI certificates \(RSA key\)) s
+5 415 M
+( spki-sign-dss OPTIONAL sign SPKI certificates \(DSS key\)) s
+5 404 M
+( pgp-sign-rsa OPTIONAL sign OpenPGP certificates \(RSA key\)) s
+5 393 M
+( pgp-sign-dss OPTIONAL sign OpenPGP certificates \(DSS key\)) s
+5 371 M
+( Additional key types may be defined as specified in [SSH-ARCH].) s
+5 349 M
+( The key type MUST always be explicitly known \(from algorithm) s
+5 338 M
+( negotiation or some other source\). It is not normally included in) s
+5 327 M
+( the key blob.) s
+5 305 M
+( Certificates and public keys are encoded as follows:) s
+5 283 M
+( string certificate or public key format identifier) s
+5 272 M
+( byte[n] key/certificate data) s
+5 250 M
+( The certificate part may have be a zero length string, but a public) s
+5 239 M
+( key is required. This is the public key that will be used for) s
+5 228 M
+( authentication; the certificate sequence contained in the certificate) s
+5 217 M
+( blob can be used to provide authorization.) s
+5 195 M
+( Public key / certifcate formats that do not explicitly specify a) s
+5 184 M
+( signature format identifier MUST use the public key / certificate) s
+5 173 M
+( format identifier as the signature identifier.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 12 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( Signatures are encoded as follows:) s
+5 679 M
+( string signature format identifier \(as specified by the) s
+5 668 M
+( public key / cert format\)) s
+5 657 M
+( byte[n] signature blob in format specific encoding.) s
+5 624 M
+( The "ssh-dss" key format has the following specific encoding:) s
+5 602 M
+( string "ssh-dss") s
+5 591 M
+( mpint p) s
+5 580 M
+( mpint q) s
+5 569 M
+( mpint g) s
+5 558 M
+( mpint y) s
+5 536 M
+( Here the p, q, g, and y parameters form the signature key blob.) s
+5 514 M
+( Signing and verifying using this key format is done according to the) s
+5 503 M
+( Digital Signature Standard [FIPS-186] using the SHA-1 hash. A) s
+5 492 M
+( description can also be found in [SCHNEIER].) s
+5 470 M
+( The resulting signature is encoded as follows:) s
+5 448 M
+( string "ssh-dss") s
+5 437 M
+( string dss_signature_blob) s
+5 415 M
+( dss_signature_blob is encoded as a string containing r followed by s) s
+5 404 M
+( \(which are 160 bits long integers, without lengths or padding,) s
+5 393 M
+( unsigned and in network byte order\).) s
+5 371 M
+( The "ssh-rsa" key format has the following specific encoding:) s
+5 349 M
+( string "ssh-rsa") s
+5 338 M
+( mpint e) s
+5 327 M
+( mpint n) s
+5 305 M
+( Here the e and n parameters form the signature key blob.) s
+5 283 M
+( Signing and verifying using this key format is done according to) s
+5 272 M
+( [SCHNEIER] and [PKCS1] using the SHA-1 hash.) s
+5 250 M
+( The resulting signature is encoded as follows:) s
+5 228 M
+( string "ssh-rsa") s
+5 217 M
+( string rsa_signature_blob) s
+5 195 M
+( rsa_signature_blob is encoded as a string containing s \(which is an) s
+5 184 M
+( integer, without lengths or padding, unsigned and in network byte) s
+5 173 M
+( order\).) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (12,13) 7
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 13 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( The "spki-sign-rsa" method indicates that the certificate blob) s
+5 679 M
+( contains a sequence of SPKI certificates. The format of SPKI) s
+5 668 M
+( certificates is described in [RFC2693]. This method indicates that) s
+5 657 M
+( the key \(or one of the keys in the certificate\) is an RSA-key.) s
+5 635 M
+( The "spki-sign-dss". As above, but indicates that the key \(or one of) s
+5 624 M
+( the keys in the certificate\) is a DSS-key.) s
+5 602 M
+( The "pgp-sign-rsa" method indicates the certificates, the public key,) s
+5 591 M
+( and the signature are in OpenPGP compatible binary format) s
+5 580 M
+( \([RFC2440]\). This method indicates that the key is an RSA-key.) s
+5 558 M
+( The "pgp-sign-dss". As above, but indicates that the key is a) s
+5 547 M
+( DSS-key.) s
+5 525 M
+(6. Key Exchange) s
+5 503 M
+( Key exchange begins by each side sending lists of supported) s
+5 492 M
+( algorithms. Each side has a preferred algorithm in each category, and) s
+5 481 M
+( it is assumed that most implementations at any given time will use) s
+5 470 M
+( the same preferred algorithm. Each side MAY guess which algorithm) s
+5 459 M
+( the other side is using, and MAY send an initial key exchange packet) s
+5 448 M
+( according to the algorithm if appropriate for the preferred method.) s
+5 426 M
+( Guess is considered wrong, if:) s
+5 415 M
+( o the kex algorithm and/or the host key algorithm is guessed wrong) s
+5 404 M
+( \(server and client have different preferred algorithm\), or) s
+5 393 M
+( o if any of the other algorithms cannot be agreed upon \(the) s
+5 382 M
+( procedure is defined below in Section Section 6.1\).) s
+5 360 M
+( Otherwise, the guess is considered to be right and the optimistically) s
+5 349 M
+( sent packet MUST be handled as the first key exchange packet.) s
+5 327 M
+( However, if the guess was wrong, and a packet was optimistically sent) s
+5 316 M
+( by one or both parties, such packets MUST be ignored \(even if the) s
+5 305 M
+( error in the guess would not affect the contents of the initial) s
+5 294 M
+( packet\(s\)\), and the appropriate side MUST send the correct initial) s
+5 283 M
+( packet.) s
+5 261 M
+( Server authentication in the key exchange MAY be implicit. After a) s
+5 250 M
+( key exchange with implicit server authentication, the client MUST) s
+5 239 M
+( wait for response to its service request message before sending any) s
+5 228 M
+( further data.) s
+5 206 M
+(6.1 Algorithm Negotiation) s
+5 184 M
+( Key exchange begins by each side sending the following packet:) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 14 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( byte SSH_MSG_KEXINIT) s
+5 679 M
+( byte[16] cookie \(random bytes\)) s
+5 668 M
+( string kex_algorithms) s
+5 657 M
+( string server_host_key_algorithms) s
+5 646 M
+( string encryption_algorithms_client_to_server) s
+5 635 M
+( string encryption_algorithms_server_to_client) s
+5 624 M
+( string mac_algorithms_client_to_server) s
+5 613 M
+( string mac_algorithms_server_to_client) s
+5 602 M
+( string compression_algorithms_client_to_server) s
+5 591 M
+( string compression_algorithms_server_to_client) s
+5 580 M
+( string languages_client_to_server) s
+5 569 M
+( string languages_server_to_client) s
+5 558 M
+( boolean first_kex_packet_follows) s
+5 547 M
+( uint32 0 \(reserved for future extension\)) s
+5 525 M
+( Each of the algorithm strings MUST be a comma-separated list of) s
+5 514 M
+( algorithm names \(see ''Algorithm Naming'' in [SSH-ARCH]\). Each) s
+5 503 M
+( supported \(allowed\) algorithm MUST be listed in order of preference.) s
+5 481 M
+( The first algorithm in each list MUST be the preferred \(guessed\)) s
+5 470 M
+( algorithm. Each string MUST contain at least one algorithm name.) s
+5 437 M
+( cookie) s
+5 426 M
+( The cookie MUST be a random value generated by the sender. Its) s
+5 415 M
+( purpose is to make it impossible for either side to fully) s
+5 404 M
+( determine the keys and the session identifier.) s
+5 382 M
+( kex_algorithms) s
+5 371 M
+( Key exchange algorithms were defined above. The first) s
+5 360 M
+( algorithm MUST be the preferred \(and guessed\) algorithm. If) s
+5 349 M
+( both sides make the same guess, that algorithm MUST be used.) s
+5 338 M
+( Otherwise, the following algorithm MUST be used to choose a key) s
+5 327 M
+( exchange method: iterate over client's kex algorithms, one at a) s
+5 316 M
+( time. Choose the first algorithm that satisfies the following) s
+5 305 M
+( conditions:) s
+5 294 M
+( + the server also supports the algorithm,) s
+5 283 M
+( + if the algorithm requires an encryption-capable host key,) s
+5 272 M
+( there is an encryption-capable algorithm on the server's) s
+5 261 M
+( server_host_key_algorithms that is also supported by the) s
+5 250 M
+( client, and) s
+5 239 M
+( + if the algorithm requires a signature-capable host key,) s
+5 228 M
+( there is a signature-capable algorithm on the server's) s
+5 217 M
+( server_host_key_algorithms that is also supported by the) s
+5 206 M
+( client.) s
+5 195 M
+( + If no algorithm satisfying all these conditions can be) s
+5 184 M
+( found, the connection fails, and both sides MUST disconnect.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (14,15) 8
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 15 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( server_host_key_algorithms) s
+5 679 M
+( List of the algorithms supported for the server host key. The) s
+5 668 M
+( server lists the algorithms for which it has host keys; the) s
+5 657 M
+( client lists the algorithms that it is willing to accept.) s
+5 646 M
+( \(There MAY be multiple host keys for a host, possibly with) s
+5 635 M
+( different algorithms.\)) s
+5 613 M
+( Some host keys may not support both signatures and encryption) s
+5 602 M
+( \(this can be determined from the algorithm\), and thus not all) s
+5 591 M
+( host keys are valid for all key exchange methods.) s
+5 569 M
+( Algorithm selection depends on whether the chosen key exchange) s
+5 558 M
+( algorithm requires a signature or encryption capable host key.) s
+5 547 M
+( It MUST be possible to determine this from the public key) s
+5 536 M
+( algorithm name. The first algorithm on the client's list that) s
+5 525 M
+( satisfies the requirements and is also supported by the server) s
+5 514 M
+( MUST be chosen. If there is no such algorithm, both sides MUST) s
+5 503 M
+( disconnect.) s
+5 481 M
+( encryption_algorithms) s
+5 470 M
+( Lists the acceptable symmetric encryption algorithms in order) s
+5 459 M
+( of preference. The chosen encryption algorithm to each) s
+5 448 M
+( direction MUST be the first algorithm on the client's list) s
+5 437 M
+( that is also on the server's list. If there is no such) s
+5 426 M
+( algorithm, both sides MUST disconnect.) s
+5 404 M
+( Note that "none" must be explicitly listed if it is to be) s
+5 393 M
+( acceptable. The defined algorithm names are listed in Section) s
+5 382 M
+( Section 5.3.) s
+5 360 M
+( mac_algorithms) s
+5 349 M
+( Lists the acceptable MAC algorithms in order of preference.) s
+5 338 M
+( The chosen MAC algorithm MUST be the first algorithm on the) s
+5 327 M
+( client's list that is also on the server's list. If there is) s
+5 316 M
+( no such algorithm, both sides MUST disconnect.) s
+5 294 M
+( Note that "none" must be explicitly listed if it is to be) s
+5 283 M
+( acceptable. The MAC algorithm names are listed in Section) s
+5 272 M
+( Figure 1.) s
+5 250 M
+( compression_algorithms) s
+5 239 M
+( Lists the acceptable compression algorithms in order of) s
+5 228 M
+( preference. The chosen compression algorithm MUST be the first) s
+5 217 M
+( algorithm on the client's list that is also on the server's) s
+5 206 M
+( list. If there is no such algorithm, both sides MUST) s
+5 195 M
+( disconnect.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 16 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( Note that "none" must be explicitly listed if it is to be) s
+5 679 M
+( acceptable. The compression algorithm names are listed in) s
+5 668 M
+( Section Section 5.2.) s
+5 646 M
+( languages) s
+5 635 M
+( This is a comma-separated list of language tags in order of) s
+5 624 M
+( preference [RFC3066]. Both parties MAY ignore this list. If) s
+5 613 M
+( there are no language preferences, this list SHOULD be empty.) s
+5 602 M
+( Language tags SHOULD NOT be present unless they are known to be) s
+5 591 M
+( needed by the sending party.) s
+5 569 M
+( first_kex_packet_follows) s
+5 558 M
+( Indicates whether a guessed key exchange packet follows. If a) s
+5 547 M
+( guessed packet will be sent, this MUST be TRUE. If no guessed) s
+5 536 M
+( packet will be sent, this MUST be FALSE.) s
+5 514 M
+( After receiving the SSH_MSG_KEXINIT packet from the other side,) s
+5 503 M
+( each party will know whether their guess was right. If the) s
+5 492 M
+( other party's guess was wrong, and this field was TRUE, the) s
+5 481 M
+( next packet MUST be silently ignored, and both sides MUST then) s
+5 470 M
+( act as determined by the negotiated key exchange method. If) s
+5 459 M
+( the guess was right, key exchange MUST continue using the) s
+5 448 M
+( guessed packet.) s
+5 426 M
+( After the KEXINIT packet exchange, the key exchange algorithm is run.) s
+5 415 M
+( It may involve several packet exchanges, as specified by the key) s
+5 404 M
+( exchange method.) s
+5 382 M
+(6.2 Output from Key Exchange) s
+5 360 M
+( The key exchange produces two values: a shared secret K, and an) s
+5 349 M
+( exchange hash H. Encryption and authentication keys are derived from) s
+5 338 M
+( these. The exchange hash H from the first key exchange is) s
+5 327 M
+( additionally used as the session identifier, which is a unique) s
+5 316 M
+( identifier for this connection. It is used by authentication methods) s
+5 305 M
+( as a part of the data that is signed as a proof of possession of a) s
+5 294 M
+( private key. Once computed, the session identifier is not changed,) s
+5 283 M
+( even if keys are later re-exchanged.) s
+5 250 M
+( Each key exchange method specifies a hash function that is used in) s
+5 239 M
+( the key exchange. The same hash algorithm MUST be used in key) s
+5 228 M
+( derivation. Here, we'll call it HASH.) s
+5 195 M
+( Encryption keys MUST be computed as HASH of a known value and K as) s
+5 184 M
+( follows:) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (16,17) 9
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 17 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( o Initial IV client to server: HASH\(K || H || "A" || session_id\)) s
+5 679 M
+( \(Here K is encoded as mpint and "A" as byte and session_id as raw) s
+5 668 M
+( data."A" means the single character A, ASCII 65\).) s
+5 657 M
+( o Initial IV server to client: HASH\(K || H || "B" || session_id\)) s
+5 646 M
+( o Encryption key client to server: HASH\(K || H || "C" || session_id\)) s
+5 635 M
+( o Encryption key server to client: HASH\(K || H || "D" || session_id\)) s
+5 624 M
+( o Integrity key client to server: HASH\(K || H || "E" || session_id\)) s
+5 613 M
+( o Integrity key server to client: HASH\(K || H || "F" || session_id\)) s
+5 591 M
+( Key data MUST be taken from the beginning of the hash output. 128) s
+5 580 M
+( bits \(16 bytes\) MUST be used for algorithms with variable-length) s
+5 569 M
+( keys. The only variable key length algorithm defined in this document) s
+5 558 M
+( is arcfour\). For other algorithms, as many bytes as are needed are) s
+5 547 M
+( taken from the beginning of the hash value. If the key length needed) s
+5 536 M
+( is longer than the output of the HASH, the key is extended by) s
+5 525 M
+( computing HASH of the concatenation of K and H and the entire key so) s
+5 514 M
+( far, and appending the resulting bytes \(as many as HASH generates\) to) s
+5 503 M
+( the key. This process is repeated until enough key material is) s
+5 492 M
+( available; the key is taken from the beginning of this value. In) s
+5 481 M
+( other words:) s
+5 459 M
+( K1 = HASH\(K || H || X || session_id\) \(X is e.g. "A"\)) s
+5 448 M
+( K2 = HASH\(K || H || K1\)) s
+5 437 M
+( K3 = HASH\(K || H || K1 || K2\)) s
+5 426 M
+( ...) s
+5 415 M
+( key = K1 || K2 || K3 || ...) s
+5 393 M
+( This process will lose entropy if the amount of entropy in K is) s
+5 382 M
+( larger than the internal state size of HASH.) s
+5 360 M
+(6.3 Taking Keys Into Use) s
+5 338 M
+( Key exchange ends by each side sending an SSH_MSG_NEWKEYS message.) s
+5 327 M
+( This message is sent with the old keys and algorithms. All messages) s
+5 316 M
+( sent after this message MUST use the new keys and algorithms.) s
+5 283 M
+( When this message is received, the new keys and algorithms MUST be) s
+5 272 M
+( taken into use for receiving.) s
+5 239 M
+( This message is the only valid message after key exchange, in) s
+5 228 M
+( addition to SSH_MSG_DEBUG, SSH_MSG_DISCONNECT and SSH_MSG_IGNORE) s
+5 217 M
+( messages. The purpose of this message is to ensure that a party is) s
+5 206 M
+( able to respond with a disconnect message that the other party can) s
+5 195 M
+( understand if something goes wrong with the key exchange.) s
+5 184 M
+( Implementations MUST NOT accept any other messages after key exchange) s
+5 173 M
+( before receiving SSH_MSG_NEWKEYS.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 18 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( byte SSH_MSG_NEWKEYS) s
+5 657 M
+(7. Diffie-Hellman Key Exchange) s
+5 635 M
+( The Diffie-Hellman key exchange provides a shared secret that can not) s
+5 624 M
+( be determined by either party alone. The key exchange is combined) s
+5 613 M
+( with a signature with the host key to provide host authentication.) s
+5 580 M
+( In the following description \(C is the client, S is the server; p is) s
+5 569 M
+( a large safe prime, g is a generator for a subgroup of GF\(p\), and q) s
+5 558 M
+( is the order of the subgroup; V_S is S's version string; V_C is C's) s
+5 547 M
+( version string; K_S is S's public host key; I_C is C's KEXINIT) s
+5 536 M
+( message and I_S S's KEXINIT message which have been exchanged before) s
+5 525 M
+( this part begins\):) s
+5 492 M
+( 1. C generates a random number x \(1 < x < q\) and computes e = g^x) s
+5 481 M
+( mod p. C sends "e" to S.) s
+5 459 M
+( 2. S generates a random number y \(0 < y < q\) and computes f = g^y) s
+5 448 M
+( mod p. S receives "e". It computes K = e^y mod p, H = hash\(V_C) s
+5 437 M
+( || V_S || I_C || I_S || K_S || e || f || K\) \(these elements are) s
+5 426 M
+( encoded according to their types; see below\), and signature s on) s
+5 415 M
+( H with its private host key. S sends "K_S || f || s" to C. The) s
+5 404 M
+( signing operation may involve a second hashing operation.) s
+5 382 M
+( 3. C verifies that K_S really is the host key for S \(e.g. using) s
+5 371 M
+( certificates or a local database\). C is also allowed to accept) s
+5 360 M
+( the key without verification; however, doing so will render the) s
+5 349 M
+( protocol insecure against active attacks \(but may be desirable) s
+5 338 M
+( for practical reasons in the short term in many environments\). C) s
+5 327 M
+( then computes K = f^x mod p, H = hash\(V_C || V_S || I_C || I_S ||) s
+5 316 M
+( K_S || e || f || K\), and verifies the signature s on H.) s
+5 294 M
+( Either side MUST NOT send or accept e or f values that are not in the) s
+5 283 M
+( range [1, p-1]. If this condition is violated, the key exchange) s
+5 272 M
+( fails.) s
+5 239 M
+( This is implemented with the following messages. The hash algorithm) s
+5 228 M
+( for computing the exchange hash is defined by the method name, and is) s
+5 217 M
+( called HASH. The public key algorithm for signing is negotiated with) s
+5 206 M
+( the KEXINIT messages.) s
+5 184 M
+( First, the client sends the following:) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (18,19) 10
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 19 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( byte SSH_MSG_KEXDH_INIT) s
+5 679 M
+( mpint e) s
+5 646 M
+( The server responds with the following:) s
+5 624 M
+( byte SSH_MSG_KEXDH_REPLY) s
+5 613 M
+( string server public host key and certificates \(K_S\)) s
+5 602 M
+( mpint f) s
+5 591 M
+( string signature of H) s
+5 569 M
+( The hash H is computed as the HASH hash of the concatenation of the) s
+5 558 M
+( following:) s
+5 536 M
+( string V_C, the client's version string \(CR and NL excluded\)) s
+5 525 M
+( string V_S, the server's version string \(CR and NL excluded\)) s
+5 514 M
+( string I_C, the payload of the client's SSH_MSG_KEXINIT) s
+5 503 M
+( string I_S, the payload of the server's SSH_MSG_KEXINIT) s
+5 492 M
+( string K_S, the host key) s
+5 481 M
+( mpint e, exchange value sent by the client) s
+5 470 M
+( mpint f, exchange value sent by the server) s
+5 459 M
+( mpint K, the shared secret) s
+5 437 M
+( This value is called the exchange hash, and it is used to) s
+5 426 M
+( authenticate the key exchange. The exchange hash SHOULD be kept) s
+5 415 M
+( secret.) s
+5 382 M
+( The signature algorithm MUST be applied over H, not the original) s
+5 371 M
+( data. Most signature algorithms include hashing and additional) s
+5 360 M
+( padding. For example, "ssh-dss" specifies SHA-1 hashing; in that) s
+5 349 M
+( case, the data is first hashed with HASH to compute H, and H is then) s
+5 338 M
+( hashed with SHA-1 as part of the signing operation.) s
+5 316 M
+(7.1 diffie-hellman-group1-sha1) s
+5 294 M
+( The "diffie-hellman-group1-sha1" method specifies Diffie-Hellman key) s
+5 283 M
+( exchange with SHA-1 as HASH, and Oakley group 14 [RFC3526] \(2048-bit) s
+5 272 M
+( MODP Group\). It is included below in hexadecimal and decimal.) s
+5 250 M
+( The prime p is equal to 2^1024 - 2^960 - 1 + 2^64 * floor\( 2^894 Pi +) s
+5 239 M
+( 129093 \). Its hexadecimal value is:) s
+5 217 M
+( FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1) s
+5 206 M
+( 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD) s
+5 195 M
+( EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245) s
+5 184 M
+( E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED) s
+5 173 M
+( EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 20 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( FFFFFFFF FFFFFFFF.) s
+5 668 M
+( In decimal, this value is:) s
+5 646 M
+( 179769313486231590770839156793787453197860296048756011706444) s
+5 635 M
+( 423684197180216158519368947833795864925541502180565485980503) s
+5 624 M
+( 646440548199239100050792877003355816639229553136239076508735) s
+5 613 M
+( 759914822574862575007425302077447712589550957937778424442426) s
+5 602 M
+( 617334727629299387668709205606050270810842907692932019128194) s
+5 591 M
+( 467627007.) s
+5 569 M
+( The generator used with this prime is g = 2. The group order q is \(p) s
+5 558 M
+( - 1\) / 2.) s
+5 536 M
+(8. Key Re-Exchange) s
+5 514 M
+( Key re-exchange is started by sending an SSH_MSG_KEXINIT packet when) s
+5 503 M
+( not already doing a key exchange \(as described in Section Section) s
+5 492 M
+( 6.1\). When this message is received, a party MUST respond with its) s
+5 481 M
+( own SSH_MSG_KEXINIT message except when the received SSH_MSG_KEXINIT) s
+5 470 M
+( already was a reply. Either party MAY initiate the re-exchange, but) s
+5 459 M
+( roles MUST NOT be changed \(i.e., the server remains the server, and) s
+5 448 M
+( the client remains the client\).) s
+5 415 M
+( Key re-exchange is performed using whatever encryption was in effect) s
+5 404 M
+( when the exchange was started. Encryption, compression, and MAC) s
+5 393 M
+( methods are not changed before a new SSH_MSG_NEWKEYS is sent after) s
+5 382 M
+( the key exchange \(as in the initial key exchange\). Re-exchange is) s
+5 371 M
+( processed identically to the initial key exchange, except for the) s
+5 360 M
+( session identifier that will remain unchanged. It is permissible to) s
+5 349 M
+( change some or all of the algorithms during the re-exchange. Host) s
+5 338 M
+( keys can also change. All keys and initialization vectors are) s
+5 327 M
+( recomputed after the exchange. Compression and encryption contexts) s
+5 316 M
+( are reset.) s
+5 283 M
+( It is recommended that the keys are changed after each gigabyte of) s
+5 272 M
+( transmitted data or after each hour of connection time, whichever) s
+5 261 M
+( comes sooner. However, since the re-exchange is a public key) s
+5 250 M
+( operation, it requires a fair amount of processing power and should) s
+5 239 M
+( not be performed too often.) s
+5 206 M
+( More application data may be sent after the SSH_MSG_NEWKEYS packet) s
+5 195 M
+( has been sent; key exchange does not affect the protocols that lie) s
+5 184 M
+( above the SSH transport layer.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (20,21) 11
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 21 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+(9. Service Request) s
+5 668 M
+( After the key exchange, the client requests a service. The service is) s
+5 657 M
+( identified by a name. The format of names and procedures for defining) s
+5 646 M
+( new names are defined in [SSH-ARCH].) s
+5 613 M
+( Currently, the following names have been reserved:) s
+5 591 M
+( ssh-userauth) s
+5 580 M
+( ssh-connection) s
+5 558 M
+( Similar local naming policy is applied to the service names, as is) s
+5 547 M
+( applied to the algorithm names; a local service should use the) s
+5 536 M
+( "servicename@domain" syntax.) s
+5 514 M
+( byte SSH_MSG_SERVICE_REQUEST) s
+5 503 M
+( string service name) s
+5 481 M
+( If the server rejects the service request, it SHOULD send an) s
+5 470 M
+( appropriate SSH_MSG_DISCONNECT message and MUST disconnect.) s
+5 437 M
+( When the service starts, it may have access to the session identifier) s
+5 426 M
+( generated during the key exchange.) s
+5 393 M
+( If the server supports the service \(and permits the client to use) s
+5 382 M
+( it\), it MUST respond with the following:) s
+5 360 M
+( byte SSH_MSG_SERVICE_ACCEPT) s
+5 349 M
+( string service name) s
+5 327 M
+( Message numbers used by services should be in the area reserved for) s
+5 316 M
+( them \(see Section 6 in [SSH-ARCH]\). The transport level will) s
+5 305 M
+( continue to process its own messages.) s
+5 272 M
+( Note that after a key exchange with implicit server authentication,) s
+5 261 M
+( the client MUST wait for response to its service request message) s
+5 250 M
+( before sending any further data.) s
+5 228 M
+(10. Additional Messages) s
+5 206 M
+( Either party may send any of the following messages at any time.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 22 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+(10.1 Disconnection Message) s
+5 668 M
+( byte SSH_MSG_DISCONNECT) s
+5 657 M
+( uint32 reason code) s
+5 646 M
+( string description [RFC2279]) s
+5 635 M
+( string language tag [RFC3066]) s
+5 613 M
+( This message causes immediate termination of the connection. All) s
+5 602 M
+( implementations MUST be able to process this message; they SHOULD be) s
+5 591 M
+( able to send this message.) s
+5 569 M
+( The sender MUST NOT send or receive any data after this message, and) s
+5 558 M
+( the recipient MUST NOT accept any data after receiving this message.) s
+5 547 M
+( The description field gives a more specific explanation in a) s
+5 536 M
+( human-readable form. The error code gives the reason in a more) s
+5 525 M
+( machine-readable format \(suitable for localization\), and can have the) s
+5 514 M
+( following values:) s
+5 492 M
+( #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1) s
+5 481 M
+( #define SSH_DISCONNECT_PROTOCOL_ERROR 2) s
+5 470 M
+( #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3) s
+5 459 M
+( #define SSH_DISCONNECT_RESERVED 4) s
+5 448 M
+( #define SSH_DISCONNECT_MAC_ERROR 5) s
+5 437 M
+( #define SSH_DISCONNECT_COMPRESSION_ERROR 6) s
+5 426 M
+( #define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7) s
+5 415 M
+( #define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8) s
+5 404 M
+( #define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9) s
+5 393 M
+( #define SSH_DISCONNECT_CONNECTION_LOST 10) s
+5 382 M
+( #define SSH_DISCONNECT_BY_APPLICATION 11) s
+5 371 M
+( #define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12) s
+5 360 M
+( #define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13) s
+5 349 M
+( #define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14) s
+5 338 M
+( #define SSH_DISCONNECT_ILLEGAL_USER_NAME 15) s
+5 316 M
+( If the description string is displayed, control character filtering) s
+5 305 M
+( discussed in [SSH-ARCH] should be used to avoid attacks by sending) s
+5 294 M
+( terminal control characters.) s
+5 272 M
+(10.2 Ignored Data Message) s
+5 250 M
+( byte SSH_MSG_IGNORE) s
+5 239 M
+( string data) s
+5 217 M
+( All implementations MUST understand \(and ignore\) this message at any) s
+5 206 M
+( time \(after receiving the protocol version\). No implementation is) s
+5 195 M
+( required to send them. This message can be used as an additional) s
+5 184 M
+( protection measure against advanced traffic analysis techniques.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (22,23) 12
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 23 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+(10.3 Debug Message) s
+5 668 M
+( byte SSH_MSG_DEBUG) s
+5 657 M
+( boolean always_display) s
+5 646 M
+( string message [RFC2279]) s
+5 635 M
+( string language tag [RFC3066]) s
+5 613 M
+( All implementations MUST understand this message, but they are) s
+5 602 M
+( allowed to ignore it. This message is used to pass the other side) s
+5 591 M
+( information that may help debugging. If always_display is TRUE, the) s
+5 580 M
+( message SHOULD be displayed. Otherwise, it SHOULD NOT be displayed) s
+5 569 M
+( unless debugging information has been explicitly requested by the) s
+5 558 M
+( user.) s
+5 525 M
+( The message doesn't need to contain a newline. It is, however,) s
+5 514 M
+( allowed to consist of multiple lines separated by CRLF \(Carriage) s
+5 503 M
+( Return - Line Feed\) pairs.) s
+5 470 M
+( If the message string is displayed, terminal control character) s
+5 459 M
+( filtering discussed in [SSH-ARCH] should be used to avoid attacks by) s
+5 448 M
+( sending terminal control characters.) s
+5 426 M
+(10.4 Reserved Messages) s
+5 404 M
+( An implementation MUST respond to all unrecognized messages with an) s
+5 393 M
+( SSH_MSG_UNIMPLEMENTED message in the order in which the messages were) s
+5 382 M
+( received. Such messages MUST be otherwise ignored. Later protocol) s
+5 371 M
+( versions may define other meanings for these message types.) s
+5 349 M
+( byte SSH_MSG_UNIMPLEMENTED) s
+5 338 M
+( uint32 packet sequence number of rejected message) s
+5 305 M
+(11. Summary of Message Numbers) s
+5 283 M
+( The following message numbers have been defined in this protocol:) s
+5 261 M
+( #define SSH_MSG_DISCONNECT 1) s
+5 250 M
+( #define SSH_MSG_IGNORE 2) s
+5 239 M
+( #define SSH_MSG_UNIMPLEMENTED 3) s
+5 228 M
+( #define SSH_MSG_DEBUG 4) s
+5 217 M
+( #define SSH_MSG_SERVICE_REQUEST 5) s
+5 206 M
+( #define SSH_MSG_SERVICE_ACCEPT 6) s
+5 184 M
+( #define SSH_MSG_KEXINIT 20) s
+5 173 M
+( #define SSH_MSG_NEWKEYS 21) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 23]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 24 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( /* Numbers 30-49 used for kex packets.) s
+5 679 M
+( Different kex methods may reuse message numbers in) s
+5 668 M
+( this range. */) s
+5 646 M
+( #define SSH_MSG_KEXDH_INIT 30) s
+5 635 M
+( #define SSH_MSG_KEXDH_REPLY 31) s
+5 602 M
+(12. IANA Considerations) s
+5 580 M
+( This document is part of a set, the IANA considerations for the SSH) s
+5 569 M
+( protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],) s
+5 558 M
+( [SSH-CONNECT] are detailed in [SSH-NUMBERS].) s
+5 536 M
+(13. Security Considerations) s
+5 514 M
+( This protocol provides a secure encrypted channel over an insecure) s
+5 503 M
+( network. It performs server host authentication, key exchange,) s
+5 492 M
+( encryption, and integrity protection. It also derives a unique) s
+5 481 M
+( session id that may be used by higher-level protocols.) s
+5 459 M
+( Full security considerations for this protocol are provided in) s
+5 448 M
+( Section 8 of [SSH-ARCH]) s
+5 426 M
+(14. Intellectual Property) s
+5 404 M
+( The IETF takes no position regarding the validity or scope of any) s
+5 393 M
+( intellectual property or other rights that might be claimed to) s
+5 382 M
+( pertain to the implementation or use of the technology described in) s
+5 371 M
+( this document or the extent to which any license under such rights) s
+5 360 M
+( might or might not be available; neither does it represent that it) s
+5 349 M
+( has made any effort to identify any such rights. Information on the) s
+5 338 M
+( IETF's procedures with respect to rights in standards-track and) s
+5 327 M
+( standards-related documentation can be found in BCP-11. Copies of) s
+5 316 M
+( claims of rights made available for publication and any assurances of) s
+5 305 M
+( licenses to be made available, or the result of an attempt made to) s
+5 294 M
+( obtain a general license or permission for the use of such) s
+5 283 M
+( proprietary rights by implementers or users of this specification can) s
+5 272 M
+( be obtained from the IETF Secretariat.) s
+5 250 M
+( The IETF has been notified of intellectual property rights claimed in) s
+5 239 M
+( regard to some or all of the specification contained in this) s
+5 228 M
+( document. For more information consult the online list of claimed) s
+5 217 M
+( rights.) s
+5 195 M
+(15. Additional Information) s
+5 173 M
+( The current document editor is: [email protected]. Comments on) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 24]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (24,25) 13
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 25 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( this internet draft should be sent to the IETF SECSH working group,) s
+5 679 M
+( details at: http://ietf.org/html.charters/secsh-charter.html) s
+5 657 M
+(Normative) s
+5 635 M
+( [SSH-ARCH]) s
+5 624 M
+( Ylonen, T., "SSH Protocol Architecture", I-D) s
+5 613 M
+( draft-ietf-architecture-15.txt, Oct 2003.) s
+5 591 M
+( [SSH-TRANS]) s
+5 580 M
+( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
+5 569 M
+( draft-ietf-transport-17.txt, Oct 2003.) s
+5 547 M
+( [SSH-USERAUTH]) s
+5 536 M
+( Ylonen, T., "SSH Authentication Protocol", I-D) s
+5 525 M
+( draft-ietf-userauth-18.txt, Oct 2003.) s
+5 503 M
+( [SSH-CONNECT]) s
+5 492 M
+( Ylonen, T., "SSH Connection Protocol", I-D) s
+5 481 M
+( draft-ietf-connect-18.txt, Oct 2003.) s
+5 459 M
+( [SSH-NUMBERS]) s
+5 448 M
+( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
+5 437 M
+( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
+5 426 M
+( 2003.) s
+5 404 M
+( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
+5 393 M
+( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
+5 371 M
+(Informative) s
+5 349 M
+( [FIPS-186]) s
+5 338 M
+( Federal Information Processing Standards Publication,) s
+5 327 M
+( "FIPS PUB 186, Digital Signature Standard", May 1994.) s
+5 305 M
+( [FIPS-197]) s
+5 294 M
+( NIST, "FIPS PUB 197 Advanced Encryption Standard \(AES\)",) s
+5 283 M
+( November 2001.) s
+5 261 M
+( [FIPS-46-3]) s
+5 250 M
+( U.S. Dept. of Commerce, "FIPS PUB 46-3, Data Encryption) s
+5 239 M
+( Standard \(DES\)", October 1999.) s
+5 217 M
+( [RFC2459] Housley, R., Ford, W., Polk, T. and D. Solo, "Internet) s
+5 206 M
+( X.509 Public Key Infrastructure Certificate and CRL) s
+5 195 M
+( Profile", RFC 2459, January 1999.) s
+5 173 M
+( [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 25]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 26 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( STD 13, RFC 1034, November 1987.) s
+5 668 M
+( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
+5 657 M
+( Languages", BCP 47, RFC 3066, January 2001.) s
+5 635 M
+( [RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data Format) s
+5 624 M
+( Specification version 3.3", RFC 1950, May 1996.) s
+5 602 M
+( [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification) s
+5 591 M
+( version 1.3", RFC 1951, May 1996.) s
+5 569 M
+( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
+5 558 M
+( 10646", RFC 2279, January 1998.) s
+5 536 M
+( [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:) s
+5 525 M
+( Keyed-Hashing for Message Authentication", RFC 2104,) s
+5 514 M
+( February 1997.) s
+5 492 M
+( [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144,) s
+5 481 M
+( May 1997.) s
+5 459 M
+( [RFC2440] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer,) s
+5 448 M
+( "OpenPGP Message Format", RFC 2440, November 1998.) s
+5 426 M
+( [RFC2693] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas,) s
+5 415 M
+( B. and T. Ylonen, "SPKI Certificate Theory", RFC 2693,) s
+5 404 M
+( September 1999.) s
+5 382 M
+( [RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential \(MODP\)) s
+5 371 M
+( Diffie-Hellman groups for Internet Key Exchange \(IKE\)",) s
+5 360 M
+( RFC 3526, May 2003.) s
+5 338 M
+( [SCHNEIER]) s
+5 327 M
+( Schneier, B., "Applied Cryptography Second Edition:) s
+5 316 M
+( protocols algorithms and source in code in C", 1996.) s
+5 294 M
+( [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A) s
+5 283 M
+( 128-Bit Block Cipher, 1st Edition", March 1999.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 26]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (26,27) 14
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 27 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+(Authors' Addresses) s
+5 668 M
+( Tatu Ylonen) s
+5 657 M
+( SSH Communications Security Corp) s
+5 646 M
+( Fredrikinkatu 42) s
+5 635 M
+( HELSINKI FIN-00100) s
+5 624 M
+( Finland) s
+5 602 M
+( EMail: [email protected]) s
+5 569 M
+( Darren J. Moffat \(editor\)) s
+5 558 M
+( Sun Microsystems, Inc) s
+5 547 M
+( 17 Network Circle) s
+5 536 M
+( Menlo Park 95025) s
+5 525 M
+( USA) s
+5 503 M
+( EMail: [email protected]) s
+5 481 M
+(Appendix A. Contibutors) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 27]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 28 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+(Intellectual Property Statement) s
+5 668 M
+( The IETF takes no position regarding the validity or scope of any) s
+5 657 M
+( intellectual property or other rights that might be claimed to) s
+5 646 M
+( pertain to the implementation or use of the technology described in) s
+5 635 M
+( this document or the extent to which any license under such rights) s
+5 624 M
+( might or might not be available; neither does it represent that it) s
+5 613 M
+( has made any effort to identify any such rights. Information on the) s
+5 602 M
+( IETF's procedures with respect to rights in standards-track and) s
+5 591 M
+( standards-related documentation can be found in BCP-11. Copies of) s
+5 580 M
+( claims of rights made available for publication and any assurances of) s
+5 569 M
+( licenses to be made available, or the result of an attempt made to) s
+5 558 M
+( obtain a general license or permission for the use of such) s
+5 547 M
+( proprietary rights by implementors or users of this specification can) s
+5 536 M
+( be obtained from the IETF Secretariat.) s
+5 514 M
+( The IETF invites any interested party to bring to its attention any) s
+5 503 M
+( copyrights, patents or patent applications, or other proprietary) s
+5 492 M
+( rights which may cover technology that may be required to practice) s
+5 481 M
+( this standard. Please address the information to the IETF Executive) s
+5 470 M
+( Director.) s
+5 448 M
+( The IETF has been notified of intellectual property rights claimed in) s
+5 437 M
+( regard to some or all of the specification contained in this) s
+5 426 M
+( document. For more information consult the online list of claimed) s
+5 415 M
+( rights.) s
+5 382 M
+(Full Copyright Statement) s
+5 360 M
+( Copyright \(C\) The Internet Society \(2003\). All Rights Reserved.) s
+5 338 M
+( This document and translations of it may be copied and furnished to) s
+5 327 M
+( others, and derivative works that comment on or otherwise explain it) s
+5 316 M
+( or assist in its implementation may be prepared, copied, published) s
+5 305 M
+( and distributed, in whole or in part, without restriction of any) s
+5 294 M
+( kind, provided that the above copyright notice and this paragraph are) s
+5 283 M
+( included on all such copies and derivative works. However, this) s
+5 272 M
+( document itself may not be modified in any way, such as by removing) s
+5 261 M
+( the copyright notice or references to the Internet Society or other) s
+5 250 M
+( Internet organizations, except as needed for the purpose of) s
+5 239 M
+( developing Internet standards in which case the procedures for) s
+5 228 M
+( copyrights defined in the Internet Standards process must be) s
+5 217 M
+( followed, or as required to translate it into languages other than) s
+5 206 M
+( English.) s
+5 184 M
+( The limited permissions granted above are perpetual and will not be) s
+5 173 M
+( revoked by the Internet Society or its successors or assignees.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 28]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (28,29) 15
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 29 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Transport Layer Protocol Oct 2003) s
+5 690 M
+( This document and the information contained herein is provided on an) s
+5 679 M
+( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
+5 668 M
+( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
+5 657 M
+( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
+5 646 M
+( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
+5 635 M
+( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
+5 602 M
+(Acknowledgment) s
+5 580 M
+( Funding for the RFC Editor function is currently provided by the) s
+5 569 M
+( Internet Society.) s
+5 129 M
+(Ylonen & Moffat, Editor Expires March 31, 2004 [Page 29]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+showpage
+PStoPSsaved restore
+%%Trailer
+%%Pages: 29
+%%DocumentNeededResources: font Courier-Bold Courier
+%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt
new file mode 100644
index 0000000000..9073ea52b2
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-transport-17.txt
@@ -0,0 +1,1624 @@
+
+
+
+Network Working Group T. Ylonen
+Internet-Draft SSH Communications Security Corp
+Expires: March 31, 2004 D. Moffat, Editor, Ed.
+ Sun Microsystems, Inc
+ Oct 2003
+
+
+ SSH Transport Layer Protocol
+ draft-ietf-secsh-transport-17.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that other
+ groups may also distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on March 31, 2004.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ SSH is a protocol for secure remote login and other secure network
+ services over an insecure network.
+
+ This document describes the SSH transport layer protocol which
+ typically runs on top of TCP/IP. The protocol can be used as a basis
+ for a number of secure network services. It provides strong
+ encryption, server authentication, and integrity protection. It may
+ also provide compression.
+
+ Key exchange method, public key algorithm, symmetric encryption
+ algorithm, message authentication algorithm, and hash algorithm are
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 1]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ all negotiated.
+
+ This document also describes the Diffie-Hellman key exchange method
+ and the minimal set of algorithms that are needed to implement the
+ SSH transport layer protocol.
+
+Table of Contents
+
+ 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Conventions Used in This Document . . . . . . . . . . . . . 3
+ 4. Connection Setup . . . . . . . . . . . . . . . . . . . . . . 3
+ 4.1 Use over TCP/IP . . . . . . . . . . . . . . . . . . . . . . 4
+ 4.2 Protocol Version Exchange . . . . . . . . . . . . . . . . . 4
+ 4.3 Compatibility With Old SSH Versions . . . . . . . . . . . . 4
+ 4.3.1 Old Client, New Server . . . . . . . . . . . . . . . . . . . 5
+ 4.3.2 New Client, Old Server . . . . . . . . . . . . . . . . . . . 5
+ 5. Binary Packet Protocol . . . . . . . . . . . . . . . . . . . 5
+ 5.1 Maximum Packet Length . . . . . . . . . . . . . . . . . . . 6
+ 5.2 Compression . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 5.3 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 5.4 Data Integrity . . . . . . . . . . . . . . . . . . . . . . . 9
+ 5.5 Key Exchange Methods . . . . . . . . . . . . . . . . . . . . 10
+ 5.6 Public Key Algorithms . . . . . . . . . . . . . . . . . . . 11
+ 6. Key Exchange . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 6.1 Algorithm Negotiation . . . . . . . . . . . . . . . . . . . 13
+ 6.2 Output from Key Exchange . . . . . . . . . . . . . . . . . . 16
+ 6.3 Taking Keys Into Use . . . . . . . . . . . . . . . . . . . . 17
+ 7. Diffie-Hellman Key Exchange . . . . . . . . . . . . . . . . 18
+ 7.1 diffie-hellman-group1-sha1 . . . . . . . . . . . . . . . . . 19
+ 8. Key Re-Exchange . . . . . . . . . . . . . . . . . . . . . . 20
+ 9. Service Request . . . . . . . . . . . . . . . . . . . . . . 21
+ 10. Additional Messages . . . . . . . . . . . . . . . . . . . . 21
+ 10.1 Disconnection Message . . . . . . . . . . . . . . . . . . . 22
+ 10.2 Ignored Data Message . . . . . . . . . . . . . . . . . . . . 22
+ 10.3 Debug Message . . . . . . . . . . . . . . . . . . . . . . . 23
+ 10.4 Reserved Messages . . . . . . . . . . . . . . . . . . . . . 23
+ 11. Summary of Message Numbers . . . . . . . . . . . . . . . . . 23
+ 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 24
+ 13. Security Considerations . . . . . . . . . . . . . . . . . . 24
+ 14. Intellectual Property . . . . . . . . . . . . . . . . . . . 24
+ 15. Additional Information . . . . . . . . . . . . . . . . . . . 24
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 26
+ Normative . . . . . . . . . . . . . . . . . . . . . . . . . 25
+ Informative . . . . . . . . . . . . . . . . . . . . . . . . 25
+ A. Contibutors . . . . . . . . . . . . . . . . . . . . . . . . 27
+ Intellectual Property and Copyright Statements . . . . . . . 28
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 2]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+1. Contributors
+
+ The major original contributors of this document were: Tatu Ylonen,
+ Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
+ Security Corp), and Markku-Juhani O. Saarinen (University of
+ Jyvaskyla)
+
+ The document editor is: [email protected]. Comments on this
+ internet draft should be sent to the IETF SECSH working group,
+ details at: http://ietf.org/html.charters/secsh-charter.html
+
+2. Introduction
+
+ The SSH transport layer is a secure low level transport protocol. It
+ provides strong encryption, cryptographic host authentication, and
+ integrity protection.
+
+ Authentication in this protocol level is host-based; this protocol
+ does not perform user authentication. A higher level protocol for
+ user authentication can be designed on top of this protocol.
+
+ The protocol has been designed to be simple, flexible, to allow
+ parameter negotiation, and to minimize the number of round-trips.
+ Key exchange method, public key algorithm, symmetric encryption
+ algorithm, message authentication algorithm, and hash algorithm are
+ all negotiated. It is expected that in most environments, only 2
+ round-trips will be needed for full key exchange, server
+ authentication, service request, and acceptance notification of
+ service request. The worst case is 3 round-trips.
+
+3. Conventions Used in This Document
+
+ The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ and "MAY" that appear in this document are to be interpreted as
+ described in [RFC2119].
+
+ The used data types and terminology are specified in the architecture
+ document [SSH-ARCH].
+
+ The architecture document also discusses the algorithm naming
+ conventions that MUST be used with the SSH protocols.
+
+4. Connection Setup
+
+ SSH works over any 8-bit clean, binary-transparent transport. The
+ underlying transport SHOULD protect against transmission errors as
+ such errors cause the SSH connection to terminate.
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 3]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ The client initiates the connection.
+
+4.1 Use over TCP/IP
+
+ When used over TCP/IP, the server normally listens for connections on
+ port 22. This port number has been registered with the IANA, and has
+ been officially assigned for SSH.
+
+4.2 Protocol Version Exchange
+
+ When the connection has been established, both sides MUST send an
+ identification string of the form "SSH-protoversion-softwareversion
+ comments", followed by carriage return and newline characters (ASCII
+ 13 and 10, respectively). Both sides MUST be able to process
+ identification strings without carriage return character. No null
+ character is sent. The maximum length of the string is 255
+ characters, including the carriage return and newline.
+
+ The part of the identification string preceding carriage return and
+ newline is used in the Diffie-Hellman key exchange (see Section
+ Section 7).
+
+ The server MAY send other lines of data before sending the version
+ string. Each line SHOULD be terminated by a carriage return and
+ newline. Such lines MUST NOT begin with "SSH-", and SHOULD be
+ encoded in ISO-10646 UTF-8 [RFC2279] (language is not specified).
+ Clients MUST be able to process such lines; they MAY be silently
+ ignored, or MAY be displayed to the client user; if they are
+ displayed, control character filtering discussed in [SSH-ARCH] SHOULD
+ be used. The primary use of this feature is to allow TCP-wrappers to
+ display an error message before disconnecting.
+
+ Version strings MUST consist of printable US-ASCII characters, not
+ including whitespaces or a minus sign (-). The version string is
+ primarily used to trigger compatibility extensions and to indicate
+ the capabilities of an implementation. The comment string should
+ contain additional information that might be useful in solving user
+ problems.
+
+ The protocol version described in this document is 2.0.
+
+ Key exchange will begin immediately after sending this identifier.
+ All packets following the identification string SHALL use the binary
+ packet protocol, to be described below.
+
+4.3 Compatibility With Old SSH Versions
+
+ During the transition period, it is important to be able to work in a
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 4]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ way that is compatible with the installed SSH clients and servers
+ that use an older version of the protocol. Information in this
+ section is only relevant for implementations supporting compatibility
+ with SSH versions 1.x. There is no standards track or informational
+ draft available that defines the SSH 1.x protocol. The only known
+ documentation of the 1.x protocol is contained in README files that
+ are shipped along with the source code.
+
+4.3.1 Old Client, New Server
+
+ Server implementations MAY support a configurable "compatibility"
+ flag that enables compatibility with old versions. When this flag is
+ on, the server SHOULD identify its protocol version as "1.99".
+ Clients using protocol 2.0 MUST be able to identify this as identical
+ to "2.0". In this mode the server SHOULD NOT send the carriage
+ return character (ASCII 13) after the version identification string.
+
+ In the compatibility mode the server SHOULD NOT send any further data
+ after its initialization string until it has received an
+ identification string from the client. The server can then determine
+ whether the client is using an old protocol, and can revert to the
+ old protocol if required. In the compatibility mode, the server MUST
+ NOT send additional data before the version string.
+
+ When compatibility with old clients is not needed, the server MAY
+ send its initial key exchange data immediately after the
+ identification string.
+
+4.3.2 New Client, Old Server
+
+ Since the new client MAY immediately send additional data after its
+ identification string (before receiving server's identification), the
+ old protocol may already have been corrupted when the client learns
+ that the server is old. When this happens, the client SHOULD close
+ the connection to the server, and reconnect using the old protocol.
+
+5. Binary Packet Protocol
+
+ Each packet is in the following format:
+
+ uint32 packet_length
+ byte padding_length
+ byte[n1] payload; n1 = packet_length - padding_length - 1
+ byte[n2] random padding; n2 = padding_length
+ byte[m] mac (message authentication code); m = mac_length
+
+ packet_length
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 5]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ The length of the packet (bytes), not including MAC or the
+ packet_length field itself.
+
+ padding_length
+ Length of padding (bytes).
+
+ payload
+ The useful contents of the packet. If compression has been
+ negotiated, this field is compressed. Initially, compression
+ MUST be "none".
+
+ random padding
+ Arbitrary-length padding, such that the total length of
+ (packet_length || padding_length || payload || padding) is a
+ multiple of the cipher block size or 8, whichever is larger.
+ There MUST be at least four bytes of padding. The padding
+ SHOULD consist of random bytes. The maximum amount of padding
+ is 255 bytes.
+
+ mac
+ Message authentication code. If message authentication has
+ been negotiated, this field contains the MAC bytes. Initially,
+ the MAC algorithm MUST be "none".
+
+
+ Note that length of the concatenation of packet length, padding
+ length, payload, and padding MUST be a multiple of the cipher block
+ size or 8, whichever is larger. This constraint MUST be enforced
+ even when using stream ciphers. Note that the packet length field is
+ also encrypted, and processing it requires special care when sending
+ or receiving packets.
+
+ The minimum size of a packet is 16 (or the cipher block size,
+ whichever is larger) bytes (plus MAC); implementations SHOULD decrypt
+ the length after receiving the first 8 (or cipher block size,
+ whichever is larger) bytes of a packet.
+
+5.1 Maximum Packet Length
+
+ All implementations MUST be able to process packets with uncompressed
+ payload length of 32768 bytes or less and total packet size of 35000
+ bytes or less (including length, padding length, payload, padding,
+ and MAC.). The maximum of 35000 bytes is an arbitrary chosen value
+ larger than uncompressed size. Implementations SHOULD support longer
+ packets, where they might be needed, e.g. if an implementation wants
+ to send a very large number of certificates. Such packets MAY be
+ sent if the version string indicates that the other party is able to
+ process them. However, implementations SHOULD check that the packet
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 6]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ length is reasonable for the implementation to avoid
+ denial-of-service and/or buffer overflow attacks.
+
+5.2 Compression
+
+ If compression has been negotiated, the payload field (and only it)
+ will be compressed using the negotiated algorithm. The length field
+ and MAC will be computed from the compressed payload. Encryption will
+ be done after compression.
+
+ Compression MAY be stateful, depending on the method. Compression
+ MUST be independent for each direction, and implementations MUST
+ allow independently choosing the algorithm for each direction.
+
+ The following compression methods are currently defined:
+
+ none REQUIRED no compression
+ zlib OPTIONAL ZLIB (LZ77) compression
+
+ The "zlib" compression is described in [RFC1950] and in [RFC1951].
+ The compression context is initialized after each key exchange, and
+ is passed from one packet to the next with only a partial flush being
+ performed at the end of each packet. A partial flush means that the
+ current compressed block is ended and all data will be output. If the
+ current block is not a stored block, one or more empty blocks are
+ added after the current block to ensure that there are at least 8
+ bits counting from the start of the end-of-block code of the current
+ block to the end of the packet payload.
+
+ Additional methods may be defined as specified in [SSH-ARCH].
+
+5.3 Encryption
+
+ An encryption algorithm and a key will be negotiated during the key
+ exchange. When encryption is in effect, the packet length, padding
+ length, payload and padding fields of each packet MUST be encrypted
+ with the given algorithm.
+
+ The encrypted data in all packets sent in one direction SHOULD be
+ considered a single data stream. For example, initialization vectors
+ SHOULD be passed from the end of one packet to the beginning of the
+ next packet. All ciphers SHOULD use keys with an effective key length
+ of 128 bits or more.
+
+ The ciphers in each direction MUST run independently of each other,
+ and implementations MUST allow independently choosing the algorithm
+ for each direction (if multiple algorithms are allowed by local
+ policy).
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 7]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ The following ciphers are currently defined:
+
+ 3des-cbc REQUIRED three-key 3DES in CBC mode
+ blowfish-cbc OPTIONALi Blowfish in CBC mode
+ twofish256-cbc OPTIONAL Twofish in CBC mode,
+ with 256-bit key
+ twofish-cbc OPTIONAL alias for "twofish256-cbc" (this
+ is being retained for
+ historical reasons)
+ twofish192-cbc OPTIONAL Twofish with 192-bit key
+ twofish128-cbc OPTIONAL Twofish with 128-bit key
+ aes256-cbc OPTIONAL AES (Rijndael) in CBC mode,
+ with 256-bit key
+ aes192-cbc OPTIONAL AES with 192-bit key
+ aes128-cbc RECOMMENDED AES with 128-bit key
+ serpent256-cbc OPTIONAL Serpent in CBC mode, with
+ 256-bit key
+ serpent192-cbc OPTIONAL Serpent with 192-bit key
+ serpent128-cbc OPTIONAL Serpent with 128-bit key
+ arcfour OPTIONAL the ARCFOUR stream cipher
+ idea-cbc OPTIONAL IDEA in CBC mode
+ cast128-cbc OPTIONAL CAST-128 in CBC mode
+ none OPTIONAL no encryption; NOT RECOMMENDED
+
+ The "3des-cbc" cipher is three-key triple-DES
+ (encrypt-decrypt-encrypt), where the first 8 bytes of the key are
+ used for the first encryption, the next 8 bytes for the decryption,
+ and the following 8 bytes for the final encryption. This requires 24
+ bytes of key data (of which 168 bits are actually used). To
+ implement CBC mode, outer chaining MUST be used (i.e., there is only
+ one initialization vector). This is a block cipher with 8 byte
+ blocks. This algorithm is defined in [FIPS-46-3]
+
+ The "blowfish-cbc" cipher is Blowfish in CBC mode, with 128 bit keys
+ [SCHNEIER]. This is a block cipher with 8 byte blocks.
+
+ The "twofish-cbc" or "twofish256-cbc" cipher is Twofish in CBC mode,
+ with 256 bit keys as described [TWOFISH]. This is a block cipher with
+ 16 byte blocks.
+
+ The "twofish192-cbc" cipher. Same as above but with 192-bit key.
+
+ The "twofish128-cbc" cipher. Same as above but with 128-bit key.
+
+ The "aes256-cbc" cipher is AES (Advanced Encryption Standard)
+ [FIPS-197], formerly Rijndael, in CBC mode. This version uses 256-bit
+ key.
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 8]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ The "aes192-cbc" cipher. Same as above but with 192-bit key.
+
+ The "aes128-cbc" cipher. Same as above but with 128-bit key.
+
+ The "serpent256-cbc" cipher in CBC mode, with 256-bit key as
+ described in the Serpent AES submission.
+
+ The "serpent192-cbc" cipher. Same as above but with 192-bit key.
+
+ The "serpent128-cbc" cipher. Same as above but with 128-bit key.
+
+ The "arcfour" is the Arcfour stream cipher with 128 bit keys. The
+ Arcfour cipher is believed to be compatible with the RC4 cipher
+ [SCHNEIER]. RC4 is a registered trademark of RSA Data Security Inc.
+ Arcfour (and RC4) has problems with weak keys, and should be used
+ with caution.
+
+ The "idea-cbc" cipher is the IDEA cipher in CBC mode [SCHNEIER].
+
+ The "cast128-cbc" cipher is the CAST-128 cipher in CBC mode
+ [RFC2144].
+
+ The "none" algorithm specifies that no encryption is to be done.
+ Note that this method provides no confidentiality protection, and it
+ is not recommended. Some functionality (e.g. password
+ authentication) may be disabled for security reasons if this cipher
+ is chosen.
+
+ Additional methods may be defined as specified in [SSH-ARCH].
+
+5.4 Data Integrity
+
+ Data integrity is protected by including with each packet a message
+ authentication code (MAC) that is computed from a shared secret,
+ packet sequence number, and the contents of the packet.
+
+ The message authentication algorithm and key are negotiated during
+ key exchange. Initially, no MAC will be in effect, and its length
+ MUST be zero. After key exchange, the selected MAC will be computed
+ before encryption from the concatenation of packet data:
+
+ mac = MAC(key, sequence_number || unencrypted_packet)
+
+ where unencrypted_packet is the entire packet without MAC (the length
+ fields, payload and padding), and sequence_number is an implicit
+ packet sequence number represented as uint32. The sequence number is
+ initialized to zero for the first packet, and is incremented after
+ every packet (regardless of whether encryption or MAC is in use). It
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 9]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ is never reset, even if keys/algorithms are renegotiated later. It
+ wraps around to zero after every 2^32 packets. The packet sequence
+ number itself is not included in the packet sent over the wire.
+
+ The MAC algorithms for each direction MUST run independently, and
+ implementations MUST allow choosing the algorithm independently for
+ both directions.
+
+ The MAC bytes resulting from the MAC algorithm MUST be transmitted
+ without encryption as the last part of the packet. The number of MAC
+ bytes depends on the algorithm chosen.
+
+ The following MAC algorithms are currently defined:
+
+ hmac-sha1 REQUIRED HMAC-SHA1 (digest length = key
+ length = 20)
+ hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest
+ length = 12, key length = 20)
+ hmac-md5 OPTIONAL HMAC-MD5 (digest length = key
+ length = 16)
+ hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest
+ length = 12, key length = 16)
+ none OPTIONAL no MAC; NOT RECOMMENDED
+
+ Figure 1
+
+ The "hmac-*" algorithms are described in [RFC2104] The "*-n" MACs use
+ only the first n bits of the resulting value.
+
+ The hash algorithms are described in [SCHNEIER].
+
+ Additional methods may be defined as specified in [SSH-ARCH].
+
+5.5 Key Exchange Methods
+
+ The key exchange method specifies how one-time session keys are
+ generated for encryption and for authentication, and how the server
+ authentication is done.
+
+ Only one REQUIRED key exchange method has been defined:
+
+ diffie-hellman-group1-sha1 REQUIRED
+
+ This method is described later in this document.
+
+ Additional methods may be defined as specified in [SSH-ARCH].
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 10]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+5.6 Public Key Algorithms
+
+ This protocol has been designed to be able to operate with almost any
+ public key format, encoding, and algorithm (signature and/or
+ encryption).
+
+ There are several aspects that define a public key type:
+ o Key format: how is the key encoded and how are certificates
+ represented. The key blobs in this protocol MAY contain
+ certificates in addition to keys.
+ o Signature and/or encryption algorithms. Some key types may not
+ support both signing and encryption. Key usage may also be
+ restricted by policy statements in e.g. certificates. In this
+ case, different key types SHOULD be defined for the different
+ policy alternatives.
+ o Encoding of signatures and/or encrypted data. This includes but is
+ not limited to padding, byte order, and data formats.
+
+ The following public key and/or certificate formats are currently defined:
+
+ ssh-dss REQUIRED sign Raw DSS Key
+ ssh-rsa RECOMMENDED sign Raw RSA Key
+ x509v3-sign-rsa OPTIONAL sign X.509 certificates (RSA key)
+ x509v3-sign-dss OPTIONAL sign X.509 certificates (DSS key)
+ spki-sign-rsa OPTIONAL sign SPKI certificates (RSA key)
+ spki-sign-dss OPTIONAL sign SPKI certificates (DSS key)
+ pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key)
+ pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key)
+
+ Additional key types may be defined as specified in [SSH-ARCH].
+
+ The key type MUST always be explicitly known (from algorithm
+ negotiation or some other source). It is not normally included in
+ the key blob.
+
+ Certificates and public keys are encoded as follows:
+
+ string certificate or public key format identifier
+ byte[n] key/certificate data
+
+ The certificate part may have be a zero length string, but a public
+ key is required. This is the public key that will be used for
+ authentication; the certificate sequence contained in the certificate
+ blob can be used to provide authorization.
+
+ Public key / certifcate formats that do not explicitly specify a
+ signature format identifier MUST use the public key / certificate
+ format identifier as the signature identifier.
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 11]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ Signatures are encoded as follows:
+ string signature format identifier (as specified by the
+ public key / cert format)
+ byte[n] signature blob in format specific encoding.
+
+
+ The "ssh-dss" key format has the following specific encoding:
+
+ string "ssh-dss"
+ mpint p
+ mpint q
+ mpint g
+ mpint y
+
+ Here the p, q, g, and y parameters form the signature key blob.
+
+ Signing and verifying using this key format is done according to the
+ Digital Signature Standard [FIPS-186] using the SHA-1 hash. A
+ description can also be found in [SCHNEIER].
+
+ The resulting signature is encoded as follows:
+
+ string "ssh-dss"
+ string dss_signature_blob
+
+ dss_signature_blob is encoded as a string containing r followed by s
+ (which are 160 bits long integers, without lengths or padding,
+ unsigned and in network byte order).
+
+ The "ssh-rsa" key format has the following specific encoding:
+
+ string "ssh-rsa"
+ mpint e
+ mpint n
+
+ Here the e and n parameters form the signature key blob.
+
+ Signing and verifying using this key format is done according to
+ [SCHNEIER] and [PKCS1] using the SHA-1 hash.
+
+ The resulting signature is encoded as follows:
+
+ string "ssh-rsa"
+ string rsa_signature_blob
+
+ rsa_signature_blob is encoded as a string containing s (which is an
+ integer, without lengths or padding, unsigned and in network byte
+ order).
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 12]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ The "spki-sign-rsa" method indicates that the certificate blob
+ contains a sequence of SPKI certificates. The format of SPKI
+ certificates is described in [RFC2693]. This method indicates that
+ the key (or one of the keys in the certificate) is an RSA-key.
+
+ The "spki-sign-dss". As above, but indicates that the key (or one of
+ the keys in the certificate) is a DSS-key.
+
+ The "pgp-sign-rsa" method indicates the certificates, the public key,
+ and the signature are in OpenPGP compatible binary format
+ ([RFC2440]). This method indicates that the key is an RSA-key.
+
+ The "pgp-sign-dss". As above, but indicates that the key is a
+ DSS-key.
+
+6. Key Exchange
+
+ Key exchange begins by each side sending lists of supported
+ algorithms. Each side has a preferred algorithm in each category, and
+ it is assumed that most implementations at any given time will use
+ the same preferred algorithm. Each side MAY guess which algorithm
+ the other side is using, and MAY send an initial key exchange packet
+ according to the algorithm if appropriate for the preferred method.
+
+ Guess is considered wrong, if:
+ o the kex algorithm and/or the host key algorithm is guessed wrong
+ (server and client have different preferred algorithm), or
+ o if any of the other algorithms cannot be agreed upon (the
+ procedure is defined below in Section Section 6.1).
+
+ Otherwise, the guess is considered to be right and the optimistically
+ sent packet MUST be handled as the first key exchange packet.
+
+ However, if the guess was wrong, and a packet was optimistically sent
+ by one or both parties, such packets MUST be ignored (even if the
+ error in the guess would not affect the contents of the initial
+ packet(s)), and the appropriate side MUST send the correct initial
+ packet.
+
+ Server authentication in the key exchange MAY be implicit. After a
+ key exchange with implicit server authentication, the client MUST
+ wait for response to its service request message before sending any
+ further data.
+
+6.1 Algorithm Negotiation
+
+ Key exchange begins by each side sending the following packet:
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 13]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ byte SSH_MSG_KEXINIT
+ byte[16] cookie (random bytes)
+ string kex_algorithms
+ string server_host_key_algorithms
+ string encryption_algorithms_client_to_server
+ string encryption_algorithms_server_to_client
+ string mac_algorithms_client_to_server
+ string mac_algorithms_server_to_client
+ string compression_algorithms_client_to_server
+ string compression_algorithms_server_to_client
+ string languages_client_to_server
+ string languages_server_to_client
+ boolean first_kex_packet_follows
+ uint32 0 (reserved for future extension)
+
+ Each of the algorithm strings MUST be a comma-separated list of
+ algorithm names (see ''Algorithm Naming'' in [SSH-ARCH]). Each
+ supported (allowed) algorithm MUST be listed in order of preference.
+
+ The first algorithm in each list MUST be the preferred (guessed)
+ algorithm. Each string MUST contain at least one algorithm name.
+
+
+ cookie
+ The cookie MUST be a random value generated by the sender. Its
+ purpose is to make it impossible for either side to fully
+ determine the keys and the session identifier.
+
+ kex_algorithms
+ Key exchange algorithms were defined above. The first
+ algorithm MUST be the preferred (and guessed) algorithm. If
+ both sides make the same guess, that algorithm MUST be used.
+ Otherwise, the following algorithm MUST be used to choose a key
+ exchange method: iterate over client's kex algorithms, one at a
+ time. Choose the first algorithm that satisfies the following
+ conditions:
+ + the server also supports the algorithm,
+ + if the algorithm requires an encryption-capable host key,
+ there is an encryption-capable algorithm on the server's
+ server_host_key_algorithms that is also supported by the
+ client, and
+ + if the algorithm requires a signature-capable host key,
+ there is a signature-capable algorithm on the server's
+ server_host_key_algorithms that is also supported by the
+ client.
+ + If no algorithm satisfying all these conditions can be
+ found, the connection fails, and both sides MUST disconnect.
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 14]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ server_host_key_algorithms
+ List of the algorithms supported for the server host key. The
+ server lists the algorithms for which it has host keys; the
+ client lists the algorithms that it is willing to accept.
+ (There MAY be multiple host keys for a host, possibly with
+ different algorithms.)
+
+ Some host keys may not support both signatures and encryption
+ (this can be determined from the algorithm), and thus not all
+ host keys are valid for all key exchange methods.
+
+ Algorithm selection depends on whether the chosen key exchange
+ algorithm requires a signature or encryption capable host key.
+ It MUST be possible to determine this from the public key
+ algorithm name. The first algorithm on the client's list that
+ satisfies the requirements and is also supported by the server
+ MUST be chosen. If there is no such algorithm, both sides MUST
+ disconnect.
+
+ encryption_algorithms
+ Lists the acceptable symmetric encryption algorithms in order
+ of preference. The chosen encryption algorithm to each
+ direction MUST be the first algorithm on the client's list
+ that is also on the server's list. If there is no such
+ algorithm, both sides MUST disconnect.
+
+ Note that "none" must be explicitly listed if it is to be
+ acceptable. The defined algorithm names are listed in Section
+ Section 5.3.
+
+ mac_algorithms
+ Lists the acceptable MAC algorithms in order of preference.
+ The chosen MAC algorithm MUST be the first algorithm on the
+ client's list that is also on the server's list. If there is
+ no such algorithm, both sides MUST disconnect.
+
+ Note that "none" must be explicitly listed if it is to be
+ acceptable. The MAC algorithm names are listed in Section
+ Figure 1.
+
+ compression_algorithms
+ Lists the acceptable compression algorithms in order of
+ preference. The chosen compression algorithm MUST be the first
+ algorithm on the client's list that is also on the server's
+ list. If there is no such algorithm, both sides MUST
+ disconnect.
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 15]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ Note that "none" must be explicitly listed if it is to be
+ acceptable. The compression algorithm names are listed in
+ Section Section 5.2.
+
+ languages
+ This is a comma-separated list of language tags in order of
+ preference [RFC3066]. Both parties MAY ignore this list. If
+ there are no language preferences, this list SHOULD be empty.
+ Language tags SHOULD NOT be present unless they are known to be
+ needed by the sending party.
+
+ first_kex_packet_follows
+ Indicates whether a guessed key exchange packet follows. If a
+ guessed packet will be sent, this MUST be TRUE. If no guessed
+ packet will be sent, this MUST be FALSE.
+
+ After receiving the SSH_MSG_KEXINIT packet from the other side,
+ each party will know whether their guess was right. If the
+ other party's guess was wrong, and this field was TRUE, the
+ next packet MUST be silently ignored, and both sides MUST then
+ act as determined by the negotiated key exchange method. If
+ the guess was right, key exchange MUST continue using the
+ guessed packet.
+
+ After the KEXINIT packet exchange, the key exchange algorithm is run.
+ It may involve several packet exchanges, as specified by the key
+ exchange method.
+
+6.2 Output from Key Exchange
+
+ The key exchange produces two values: a shared secret K, and an
+ exchange hash H. Encryption and authentication keys are derived from
+ these. The exchange hash H from the first key exchange is
+ additionally used as the session identifier, which is a unique
+ identifier for this connection. It is used by authentication methods
+ as a part of the data that is signed as a proof of possession of a
+ private key. Once computed, the session identifier is not changed,
+ even if keys are later re-exchanged.
+
+
+ Each key exchange method specifies a hash function that is used in
+ the key exchange. The same hash algorithm MUST be used in key
+ derivation. Here, we'll call it HASH.
+
+
+ Encryption keys MUST be computed as HASH of a known value and K as
+ follows:
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 16]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ o Initial IV client to server: HASH(K || H || "A" || session_id)
+ (Here K is encoded as mpint and "A" as byte and session_id as raw
+ data."A" means the single character A, ASCII 65).
+ o Initial IV server to client: HASH(K || H || "B" || session_id)
+ o Encryption key client to server: HASH(K || H || "C" || session_id)
+ o Encryption key server to client: HASH(K || H || "D" || session_id)
+ o Integrity key client to server: HASH(K || H || "E" || session_id)
+ o Integrity key server to client: HASH(K || H || "F" || session_id)
+
+ Key data MUST be taken from the beginning of the hash output. 128
+ bits (16 bytes) MUST be used for algorithms with variable-length
+ keys. The only variable key length algorithm defined in this document
+ is arcfour). For other algorithms, as many bytes as are needed are
+ taken from the beginning of the hash value. If the key length needed
+ is longer than the output of the HASH, the key is extended by
+ computing HASH of the concatenation of K and H and the entire key so
+ far, and appending the resulting bytes (as many as HASH generates) to
+ the key. This process is repeated until enough key material is
+ available; the key is taken from the beginning of this value. In
+ other words:
+
+ K1 = HASH(K || H || X || session_id) (X is e.g. "A")
+ K2 = HASH(K || H || K1)
+ K3 = HASH(K || H || K1 || K2)
+ ...
+ key = K1 || K2 || K3 || ...
+
+ This process will lose entropy if the amount of entropy in K is
+ larger than the internal state size of HASH.
+
+6.3 Taking Keys Into Use
+
+ Key exchange ends by each side sending an SSH_MSG_NEWKEYS message.
+ This message is sent with the old keys and algorithms. All messages
+ sent after this message MUST use the new keys and algorithms.
+
+
+ When this message is received, the new keys and algorithms MUST be
+ taken into use for receiving.
+
+
+ This message is the only valid message after key exchange, in
+ addition to SSH_MSG_DEBUG, SSH_MSG_DISCONNECT and SSH_MSG_IGNORE
+ messages. The purpose of this message is to ensure that a party is
+ able to respond with a disconnect message that the other party can
+ understand if something goes wrong with the key exchange.
+ Implementations MUST NOT accept any other messages after key exchange
+ before receiving SSH_MSG_NEWKEYS.
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 17]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ byte SSH_MSG_NEWKEYS
+
+
+7. Diffie-Hellman Key Exchange
+
+ The Diffie-Hellman key exchange provides a shared secret that can not
+ be determined by either party alone. The key exchange is combined
+ with a signature with the host key to provide host authentication.
+
+
+ In the following description (C is the client, S is the server; p is
+ a large safe prime, g is a generator for a subgroup of GF(p), and q
+ is the order of the subgroup; V_S is S's version string; V_C is C's
+ version string; K_S is S's public host key; I_C is C's KEXINIT
+ message and I_S S's KEXINIT message which have been exchanged before
+ this part begins):
+
+
+ 1. C generates a random number x (1 < x < q) and computes e = g^x
+ mod p. C sends "e" to S.
+
+ 2. S generates a random number y (0 < y < q) and computes f = g^y
+ mod p. S receives "e". It computes K = e^y mod p, H = hash(V_C
+ || V_S || I_C || I_S || K_S || e || f || K) (these elements are
+ encoded according to their types; see below), and signature s on
+ H with its private host key. S sends "K_S || f || s" to C. The
+ signing operation may involve a second hashing operation.
+
+ 3. C verifies that K_S really is the host key for S (e.g. using
+ certificates or a local database). C is also allowed to accept
+ the key without verification; however, doing so will render the
+ protocol insecure against active attacks (but may be desirable
+ for practical reasons in the short term in many environments). C
+ then computes K = f^x mod p, H = hash(V_C || V_S || I_C || I_S ||
+ K_S || e || f || K), and verifies the signature s on H.
+
+ Either side MUST NOT send or accept e or f values that are not in the
+ range [1, p-1]. If this condition is violated, the key exchange
+ fails.
+
+
+ This is implemented with the following messages. The hash algorithm
+ for computing the exchange hash is defined by the method name, and is
+ called HASH. The public key algorithm for signing is negotiated with
+ the KEXINIT messages.
+
+ First, the client sends the following:
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 18]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ byte SSH_MSG_KEXDH_INIT
+ mpint e
+
+
+ The server responds with the following:
+
+ byte SSH_MSG_KEXDH_REPLY
+ string server public host key and certificates (K_S)
+ mpint f
+ string signature of H
+
+ The hash H is computed as the HASH hash of the concatenation of the
+ following:
+
+ string V_C, the client's version string (CR and NL excluded)
+ string V_S, the server's version string (CR and NL excluded)
+ string I_C, the payload of the client's SSH_MSG_KEXINIT
+ string I_S, the payload of the server's SSH_MSG_KEXINIT
+ string K_S, the host key
+ mpint e, exchange value sent by the client
+ mpint f, exchange value sent by the server
+ mpint K, the shared secret
+
+ This value is called the exchange hash, and it is used to
+ authenticate the key exchange. The exchange hash SHOULD be kept
+ secret.
+
+
+ The signature algorithm MUST be applied over H, not the original
+ data. Most signature algorithms include hashing and additional
+ padding. For example, "ssh-dss" specifies SHA-1 hashing; in that
+ case, the data is first hashed with HASH to compute H, and H is then
+ hashed with SHA-1 as part of the signing operation.
+
+7.1 diffie-hellman-group1-sha1
+
+ The "diffie-hellman-group1-sha1" method specifies Diffie-Hellman key
+ exchange with SHA-1 as HASH, and Oakley group 14 [RFC3526] (2048-bit
+ MODP Group). It is included below in hexadecimal and decimal.
+
+ The prime p is equal to 2^1024 - 2^960 - 1 + 2^64 * floor( 2^894 Pi +
+ 129093 ). Its hexadecimal value is:
+
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+ E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+ EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 19]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ FFFFFFFF FFFFFFFF.
+
+ In decimal, this value is:
+
+ 179769313486231590770839156793787453197860296048756011706444
+ 423684197180216158519368947833795864925541502180565485980503
+ 646440548199239100050792877003355816639229553136239076508735
+ 759914822574862575007425302077447712589550957937778424442426
+ 617334727629299387668709205606050270810842907692932019128194
+ 467627007.
+
+ The generator used with this prime is g = 2. The group order q is (p
+ - 1) / 2.
+
+8. Key Re-Exchange
+
+ Key re-exchange is started by sending an SSH_MSG_KEXINIT packet when
+ not already doing a key exchange (as described in Section Section
+ 6.1). When this message is received, a party MUST respond with its
+ own SSH_MSG_KEXINIT message except when the received SSH_MSG_KEXINIT
+ already was a reply. Either party MAY initiate the re-exchange, but
+ roles MUST NOT be changed (i.e., the server remains the server, and
+ the client remains the client).
+
+
+ Key re-exchange is performed using whatever encryption was in effect
+ when the exchange was started. Encryption, compression, and MAC
+ methods are not changed before a new SSH_MSG_NEWKEYS is sent after
+ the key exchange (as in the initial key exchange). Re-exchange is
+ processed identically to the initial key exchange, except for the
+ session identifier that will remain unchanged. It is permissible to
+ change some or all of the algorithms during the re-exchange. Host
+ keys can also change. All keys and initialization vectors are
+ recomputed after the exchange. Compression and encryption contexts
+ are reset.
+
+
+ It is recommended that the keys are changed after each gigabyte of
+ transmitted data or after each hour of connection time, whichever
+ comes sooner. However, since the re-exchange is a public key
+ operation, it requires a fair amount of processing power and should
+ not be performed too often.
+
+
+ More application data may be sent after the SSH_MSG_NEWKEYS packet
+ has been sent; key exchange does not affect the protocols that lie
+ above the SSH transport layer.
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 20]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+9. Service Request
+
+ After the key exchange, the client requests a service. The service is
+ identified by a name. The format of names and procedures for defining
+ new names are defined in [SSH-ARCH].
+
+
+ Currently, the following names have been reserved:
+
+ ssh-userauth
+ ssh-connection
+
+ Similar local naming policy is applied to the service names, as is
+ applied to the algorithm names; a local service should use the
+ "servicename@domain" syntax.
+
+ byte SSH_MSG_SERVICE_REQUEST
+ string service name
+
+ If the server rejects the service request, it SHOULD send an
+ appropriate SSH_MSG_DISCONNECT message and MUST disconnect.
+
+
+ When the service starts, it may have access to the session identifier
+ generated during the key exchange.
+
+
+ If the server supports the service (and permits the client to use
+ it), it MUST respond with the following:
+
+ byte SSH_MSG_SERVICE_ACCEPT
+ string service name
+
+ Message numbers used by services should be in the area reserved for
+ them (see Section 6 in [SSH-ARCH]). The transport level will
+ continue to process its own messages.
+
+
+ Note that after a key exchange with implicit server authentication,
+ the client MUST wait for response to its service request message
+ before sending any further data.
+
+10. Additional Messages
+
+ Either party may send any of the following messages at any time.
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 21]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+10.1 Disconnection Message
+
+ byte SSH_MSG_DISCONNECT
+ uint32 reason code
+ string description [RFC2279]
+ string language tag [RFC3066]
+
+ This message causes immediate termination of the connection. All
+ implementations MUST be able to process this message; they SHOULD be
+ able to send this message.
+
+ The sender MUST NOT send or receive any data after this message, and
+ the recipient MUST NOT accept any data after receiving this message.
+ The description field gives a more specific explanation in a
+ human-readable form. The error code gives the reason in a more
+ machine-readable format (suitable for localization), and can have the
+ following values:
+
+ #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
+ #define SSH_DISCONNECT_PROTOCOL_ERROR 2
+ #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3
+ #define SSH_DISCONNECT_RESERVED 4
+ #define SSH_DISCONNECT_MAC_ERROR 5
+ #define SSH_DISCONNECT_COMPRESSION_ERROR 6
+ #define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7
+ #define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8
+ #define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9
+ #define SSH_DISCONNECT_CONNECTION_LOST 10
+ #define SSH_DISCONNECT_BY_APPLICATION 11
+ #define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12
+ #define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13
+ #define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14
+ #define SSH_DISCONNECT_ILLEGAL_USER_NAME 15
+
+ If the description string is displayed, control character filtering
+ discussed in [SSH-ARCH] should be used to avoid attacks by sending
+ terminal control characters.
+
+10.2 Ignored Data Message
+
+ byte SSH_MSG_IGNORE
+ string data
+
+ All implementations MUST understand (and ignore) this message at any
+ time (after receiving the protocol version). No implementation is
+ required to send them. This message can be used as an additional
+ protection measure against advanced traffic analysis techniques.
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 22]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+10.3 Debug Message
+
+ byte SSH_MSG_DEBUG
+ boolean always_display
+ string message [RFC2279]
+ string language tag [RFC3066]
+
+ All implementations MUST understand this message, but they are
+ allowed to ignore it. This message is used to pass the other side
+ information that may help debugging. If always_display is TRUE, the
+ message SHOULD be displayed. Otherwise, it SHOULD NOT be displayed
+ unless debugging information has been explicitly requested by the
+ user.
+
+
+ The message doesn't need to contain a newline. It is, however,
+ allowed to consist of multiple lines separated by CRLF (Carriage
+ Return - Line Feed) pairs.
+
+
+ If the message string is displayed, terminal control character
+ filtering discussed in [SSH-ARCH] should be used to avoid attacks by
+ sending terminal control characters.
+
+10.4 Reserved Messages
+
+ An implementation MUST respond to all unrecognized messages with an
+ SSH_MSG_UNIMPLEMENTED message in the order in which the messages were
+ received. Such messages MUST be otherwise ignored. Later protocol
+ versions may define other meanings for these message types.
+
+ byte SSH_MSG_UNIMPLEMENTED
+ uint32 packet sequence number of rejected message
+
+
+11. Summary of Message Numbers
+
+ The following message numbers have been defined in this protocol:
+
+ #define SSH_MSG_DISCONNECT 1
+ #define SSH_MSG_IGNORE 2
+ #define SSH_MSG_UNIMPLEMENTED 3
+ #define SSH_MSG_DEBUG 4
+ #define SSH_MSG_SERVICE_REQUEST 5
+ #define SSH_MSG_SERVICE_ACCEPT 6
+
+ #define SSH_MSG_KEXINIT 20
+ #define SSH_MSG_NEWKEYS 21
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 23]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ /* Numbers 30-49 used for kex packets.
+ Different kex methods may reuse message numbers in
+ this range. */
+
+ #define SSH_MSG_KEXDH_INIT 30
+ #define SSH_MSG_KEXDH_REPLY 31
+
+
+12. IANA Considerations
+
+ This document is part of a set, the IANA considerations for the SSH
+ protocol as defined in [SSH-ARCH], [SSH-TRANS], [SSH-USERAUTH],
+ [SSH-CONNECT] are detailed in [SSH-NUMBERS].
+
+13. Security Considerations
+
+ This protocol provides a secure encrypted channel over an insecure
+ network. It performs server host authentication, key exchange,
+ encryption, and integrity protection. It also derives a unique
+ session id that may be used by higher-level protocols.
+
+ Full security considerations for this protocol are provided in
+ Section 8 of [SSH-ARCH]
+
+14. Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementers or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF has been notified of intellectual property rights claimed in
+ regard to some or all of the specification contained in this
+ document. For more information consult the online list of claimed
+ rights.
+
+15. Additional Information
+
+ The current document editor is: [email protected]. Comments on
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 24]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ this internet draft should be sent to the IETF SECSH working group,
+ details at: http://ietf.org/html.charters/secsh-charter.html
+
+Normative
+
+ [SSH-ARCH]
+ Ylonen, T., "SSH Protocol Architecture", I-D
+ draft-ietf-architecture-15.txt, Oct 2003.
+
+ [SSH-TRANS]
+ Ylonen, T., "SSH Transport Layer Protocol", I-D
+ draft-ietf-transport-17.txt, Oct 2003.
+
+ [SSH-USERAUTH]
+ Ylonen, T., "SSH Authentication Protocol", I-D
+ draft-ietf-userauth-18.txt, Oct 2003.
+
+ [SSH-CONNECT]
+ Ylonen, T., "SSH Connection Protocol", I-D
+ draft-ietf-connect-18.txt, Oct 2003.
+
+ [SSH-NUMBERS]
+ Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
+ Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
+ 2003.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+Informative
+
+ [FIPS-186]
+ Federal Information Processing Standards Publication,
+ "FIPS PUB 186, Digital Signature Standard", May 1994.
+
+ [FIPS-197]
+ NIST, "FIPS PUB 197 Advanced Encryption Standard (AES)",
+ November 2001.
+
+ [FIPS-46-3]
+ U.S. Dept. of Commerce, "FIPS PUB 46-3, Data Encryption
+ Standard (DES)", October 1999.
+
+ [RFC2459] Housley, R., Ford, W., Polk, T. and D. Solo, "Internet
+ X.509 Public Key Infrastructure Certificate and CRL
+ Profile", RFC 2459, January 1999.
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 25]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ STD 13, RFC 1034, November 1987.
+
+ [RFC3066] Alvestrand, H., "Tags for the Identification of
+ Languages", BCP 47, RFC 3066, January 2001.
+
+ [RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data Format
+ Specification version 3.3", RFC 1950, May 1996.
+
+ [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification
+ version 1.3", RFC 1951, May 1996.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+ [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC:
+ Keyed-Hashing for Message Authentication", RFC 2104,
+ February 1997.
+
+ [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144,
+ May 1997.
+
+ [RFC2440] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer,
+ "OpenPGP Message Format", RFC 2440, November 1998.
+
+ [RFC2693] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas,
+ B. and T. Ylonen, "SPKI Certificate Theory", RFC 2693,
+ September 1999.
+
+ [RFC3526] Kivinen, T. and M. Kojo, "More Modular Exponential (MODP)
+ Diffie-Hellman groups for Internet Key Exchange (IKE)",
+ RFC 3526, May 2003.
+
+ [SCHNEIER]
+ Schneier, B., "Applied Cryptography Second Edition:
+ protocols algorithms and source in code in C", 1996.
+
+ [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A
+ 128-Bit Block Cipher, 1st Edition", March 1999.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 26]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+Authors' Addresses
+
+ Tatu Ylonen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+ Darren J. Moffat (editor)
+ Sun Microsystems, Inc
+ 17 Network Circle
+ Menlo Park 95025
+ USA
+
+
+Appendix A. Contibutors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 27]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+ The IETF has been notified of intellectual property rights claimed in
+ regard to some or all of the specification contained in this
+ document. For more information consult the online list of claimed
+ rights.
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 28]
+
+Internet-Draft SSH Transport Layer Protocol Oct 2003
+
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat, Editor Expires March 31, 2004 [Page 29] \ No newline at end of file
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps
new file mode 100644
index 0000000000..be5799dbce
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.2.ps
@@ -0,0 +1,1881 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 75 0 595 747
+%%Title: Enscript Output
+%%For: Magnus Thoang
+%%Creator: GNU enscript 1.6.1
+%%CreationDate: Fri Oct 31 13:35:32 2003
+%%Orientation: Portrait
+%%Pages: 8 0
+%%DocumentMedia: A4 595 842 0 () ()
+%%DocumentNeededResources: (atend)
+%%EndComments
+%%BeginProlog
+%%BeginProcSet: PStoPS 1 15
+userdict begin
+[/showpage/erasepage/copypage]{dup where{pop dup load
+ type/operatortype eq{1 array cvx dup 0 3 index cvx put
+ bind def}{pop}ifelse}{pop}ifelse}forall
+[/letter/legal/executivepage/a4/a4small/b5/com10envelope
+ /monarchenvelope/c5envelope/dlenvelope/lettersmall/note
+ /folio/quarto/a5]{dup where{dup wcheck{exch{}put}
+ {pop{}def}ifelse}{pop}ifelse}forall
+/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}
+ {pop def}ifelse}{def}ifelse
+/PStoPSmatrix matrix currentmatrix def
+/PStoPSxform matrix def/PStoPSclip{clippath}def
+/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def
+/initmatrix{matrix defaultmatrix setmatrix}bind def
+/initclip[{matrix currentmatrix PStoPSmatrix setmatrix
+ [{currentpoint}stopped{$error/newerror false put{newpath}}
+ {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]
+ {[/newpath cvx{/moveto cvx}{/lineto cvx}
+ {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}
+ stopped{$error/errorname get/invalidaccess eq{cleartomark
+ $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop
+ /initclip dup load dup type dup/operatortype eq{pop exch pop}
+ {dup/arraytype eq exch/packedarraytype eq or
+ {dup xcheck{exch pop aload pop}{pop cvx}ifelse}
+ {pop cvx}ifelse}ifelse
+ {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def
+/initgraphics{initmatrix newpath initclip 1 setlinewidth
+ 0 setlinecap 0 setlinejoin []0 setdash 0 setgray
+ 10 setmiterlimit}bind def
+end
+%%EndProcSet
+%%BeginResource: procset Enscript-Prolog 1.6 1
+%
+% Procedures.
+%
+
+/_S { % save current state
+ /_s save def
+} def
+/_R { % restore from saved state
+ _s restore
+} def
+
+/S { % showpage protecting gstate
+ gsave
+ showpage
+ grestore
+} bind def
+
+/MF { % fontname newfontname -> - make a new encoded font
+ /newfontname exch def
+ /fontname exch def
+
+ /fontdict fontname findfont def
+ /newfont fontdict maxlength dict def
+
+ fontdict {
+ exch
+ dup /FID eq {
+ % skip FID pair
+ pop pop
+ } {
+ % copy to the new font dictionary
+ exch newfont 3 1 roll put
+ } ifelse
+ } forall
+
+ newfont /FontName newfontname put
+
+ % insert only valid encoding vectors
+ encoding_vector length 256 eq {
+ newfont /Encoding encoding_vector put
+ } if
+
+ newfontname newfont definefont pop
+} def
+
+/SF { % fontname width height -> - set a new font
+ /height exch def
+ /width exch def
+
+ findfont
+ [width 0 0 height 0 0] makefont setfont
+} def
+
+/SUF { % fontname width height -> - set a new user font
+ /height exch def
+ /width exch def
+
+ /F-gs-user-font MF
+ /F-gs-user-font width height SF
+} def
+
+/M {moveto} bind def
+/s {show} bind def
+
+/Box { % x y w h -> - define box path
+ /d_h exch def /d_w exch def /d_y exch def /d_x exch def
+ d_x d_y moveto
+ d_w 0 rlineto
+ 0 d_h rlineto
+ d_w neg 0 rlineto
+ closepath
+} def
+
+/bgs { % x y height blskip gray str -> - show string with bg color
+ /str exch def
+ /gray exch def
+ /blskip exch def
+ /height exch def
+ /y exch def
+ /x exch def
+
+ gsave
+ x y blskip sub str stringwidth pop height Box
+ gray setgray
+ fill
+ grestore
+ x y M str s
+} def
+
+% Highlight bars.
+/highlight_bars { % nlines lineheight output_y_margin gray -> -
+ gsave
+ setgray
+ /ymarg exch def
+ /lineheight exch def
+ /nlines exch def
+
+ % This 2 is just a magic number to sync highlight lines to text.
+ 0 d_header_y ymarg sub 2 sub translate
+
+ /cw d_output_w cols div def
+ /nrows d_output_h ymarg 2 mul sub lineheight div cvi def
+
+ % for each column
+ 0 1 cols 1 sub {
+ cw mul /xp exch def
+
+ % for each rows
+ 0 1 nrows 1 sub {
+ /rn exch def
+ rn lineheight mul neg /yp exch def
+ rn nlines idiv 2 mod 0 eq {
+ % Draw highlight bar. 4 is just a magic indentation.
+ xp 4 add yp cw 8 sub lineheight neg Box fill
+ } if
+ } for
+ } for
+
+ grestore
+} def
+
+% Line highlight bar.
+/line_highlight { % x y width height gray -> -
+ gsave
+ /gray exch def
+ Box gray setgray fill
+ grestore
+} def
+
+% Column separator lines.
+/column_lines {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h translate
+ /cw d_output_w cols div def
+ 1 1 cols 1 sub {
+ cw mul 0 moveto
+ 0 d_output_h rlineto stroke
+ } for
+ grestore
+} def
+
+% Column borders.
+/column_borders {
+ gsave
+ .1 setlinewidth
+ 0 d_footer_h moveto
+ 0 d_output_h rlineto
+ d_output_w 0 rlineto
+ 0 d_output_h neg rlineto
+ closepath stroke
+ grestore
+} def
+
+% Do the actual underlay drawing
+/draw_underlay {
+ ul_style 0 eq {
+ ul_str true charpath stroke
+ } {
+ ul_str show
+ } ifelse
+} def
+
+% Underlay
+/underlay { % - -> -
+ gsave
+ 0 d_page_h translate
+ d_page_h neg d_page_w atan rotate
+
+ ul_gray setgray
+ ul_font setfont
+ /dw d_page_h dup mul d_page_w dup mul add sqrt def
+ ul_str stringwidth pop dw exch sub 2 div ul_h_ptsize -2 div moveto
+ draw_underlay
+ grestore
+} def
+
+/user_underlay { % - -> -
+ gsave
+ ul_x ul_y translate
+ ul_angle rotate
+ ul_gray setgray
+ ul_font setfont
+ 0 0 ul_h_ptsize 2 div sub moveto
+ draw_underlay
+ grestore
+} def
+
+% Page prefeed
+/page_prefeed { % bool -> -
+ statusdict /prefeed known {
+ statusdict exch /prefeed exch put
+ } {
+ pop
+ } ifelse
+} def
+
+% Wrapped line markers
+/wrapped_line_mark { % x y charwith charheight type -> -
+ /type exch def
+ /h exch def
+ /w exch def
+ /y exch def
+ /x exch def
+
+ type 2 eq {
+ % Black boxes (like TeX does)
+ gsave
+ 0 setlinewidth
+ x w 4 div add y M
+ 0 h rlineto w 2 div 0 rlineto 0 h neg rlineto
+ closepath fill
+ grestore
+ } {
+ type 3 eq {
+ % Small arrows
+ gsave
+ .2 setlinewidth
+ x w 2 div add y h 2 div add M
+ w 4 div 0 rlineto
+ x w 4 div add y lineto stroke
+
+ x w 4 div add w 8 div add y h 4 div add M
+ x w 4 div add y lineto
+ w 4 div h 8 div rlineto stroke
+ grestore
+ } {
+ % do nothing
+ } ifelse
+ } ifelse
+} def
+
+% EPSF import.
+
+/BeginEPSF {
+ /b4_Inc_state save def % Save state for cleanup
+ /dict_count countdictstack def % Count objects on dict stack
+ /op_count count 1 sub def % Count objects on operand stack
+ userdict begin
+ /showpage { } def
+ 0 setgray 0 setlinecap
+ 1 setlinewidth 0 setlinejoin
+ 10 setmiterlimit [ ] 0 setdash newpath
+ /languagelevel where {
+ pop languagelevel
+ 1 ne {
+ false setstrokeadjust false setoverprint
+ } if
+ } if
+} bind def
+
+/EndEPSF {
+ count op_count sub { pos } repeat % Clean up stacks
+ countdictstack dict_count sub { end } repeat
+ b4_Inc_state restore
+} bind def
+
+% Check PostScript language level.
+/languagelevel where {
+ pop /gs_languagelevel languagelevel def
+} {
+ /gs_languagelevel 1 def
+} ifelse
+%%EndResource
+%%BeginResource: procset Enscript-Encoding-88591 1.6 1
+/encoding_vector [
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclam /quotedbl /numbersign
+/dollar /percent /ampersand /quoteright
+/parenleft /parenright /asterisk /plus
+/comma /hyphen /period /slash
+/zero /one /two /three
+/four /five /six /seven
+/eight /nine /colon /semicolon
+/less /equal /greater /question
+/at /A /B /C
+/D /E /F /G
+/H /I /J /K
+/L /M /N /O
+/P /Q /R /S
+/T /U /V /W
+/X /Y /Z /bracketleft
+/backslash /bracketright /asciicircum /underscore
+/quoteleft /a /b /c
+/d /e /f /g
+/h /i /j /k
+/l /m /n /o
+/p /q /r /s
+/t /u /v /w
+/x /y /z /braceleft
+/bar /braceright /tilde /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef
+/space /exclamdown /cent /sterling
+/currency /yen /brokenbar /section
+/dieresis /copyright /ordfeminine /guillemotleft
+/logicalnot /hyphen /registered /macron
+/degree /plusminus /twosuperior /threesuperior
+/acute /mu /paragraph /bullet
+/cedilla /onesuperior /ordmasculine /guillemotright
+/onequarter /onehalf /threequarters /questiondown
+/Agrave /Aacute /Acircumflex /Atilde
+/Adieresis /Aring /AE /Ccedilla
+/Egrave /Eacute /Ecircumflex /Edieresis
+/Igrave /Iacute /Icircumflex /Idieresis
+/Eth /Ntilde /Ograve /Oacute
+/Ocircumflex /Otilde /Odieresis /multiply
+/Oslash /Ugrave /Uacute /Ucircumflex
+/Udieresis /Yacute /Thorn /germandbls
+/agrave /aacute /acircumflex /atilde
+/adieresis /aring /ae /ccedilla
+/egrave /eacute /ecircumflex /edieresis
+/igrave /iacute /icircumflex /idieresis
+/eth /ntilde /ograve /oacute
+/ocircumflex /otilde /odieresis /divide
+/oslash /ugrave /uacute /ucircumflex
+/udieresis /yacute /thorn /ydieresis
+] def
+%%EndResource
+%%EndProlog
+%%BeginSetup
+%%IncludeResource: font Courier-Bold
+%%IncludeResource: font Courier
+/HFpt_w 10 def
+/HFpt_h 10 def
+/Courier-Bold /HF-gs-font MF
+/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def
+/Courier /F-gs-font MF
+/F-gs-font 10 10 SF
+/#copies 1 def
+/d_page_w 520 def
+/d_page_h 747 def
+/d_header_x 0 def
+/d_header_y 747 def
+/d_header_w 520 def
+/d_header_h 0 def
+/d_footer_x 0 def
+/d_footer_y 0 def
+/d_footer_w 520 def
+/d_footer_h 0 def
+/d_output_w 520 def
+/d_output_h 747 def
+/cols 1 def
+userdict/PStoPSxform PStoPSmatrix matrix currentmatrix
+ matrix invertmatrix matrix concatmatrix
+ matrix invertmatrix put
+%%EndSetup
+%%Page: (0,1) 1
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 1 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 701 M
+(Network Working Group T. Ylonen) s
+5 690 M
+(Internet-Draft SSH Communications Security Corp) s
+5 679 M
+(Expires: March 2, 2003 D. Moffat, Ed.) s
+5 668 M
+( Sun Microsystems, Inc) s
+5 657 M
+( September 2002) s
+5 624 M
+( SSH Authentication Protocol) s
+5 613 M
+( draft-ietf-secsh-userauth-18.txt) s
+5 591 M
+(Status of this Memo) s
+5 569 M
+( This document is an Internet-Draft and is in full conformance with) s
+5 558 M
+( all provisions of Section 10 of RFC2026.) s
+5 536 M
+( Internet-Drafts are working documents of the Internet Engineering) s
+5 525 M
+( Task Force \(IETF\), its areas, and its working groups. Note that other) s
+5 514 M
+( groups may also distribute working documents as Internet-Drafts.) s
+5 492 M
+( Internet-Drafts are draft documents valid for a maximum of six months) s
+5 481 M
+( and may be updated, replaced, or obsoleted by other documents at any) s
+5 470 M
+( time. It is inappropriate to use Internet-Drafts as reference) s
+5 459 M
+( material or to cite them other than as "work in progress.") s
+5 437 M
+( The list of current Internet-Drafts can be accessed at http://) s
+5 426 M
+( www.ietf.org/ietf/1id-abstracts.txt.) s
+5 404 M
+( The list of Internet-Draft Shadow Directories can be accessed at) s
+5 393 M
+( http://www.ietf.org/shadow.html.) s
+5 371 M
+( This Internet-Draft will expire on March 2, 2003.) s
+5 349 M
+(Copyright Notice) s
+5 327 M
+( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
+5 305 M
+(Abstract) s
+5 283 M
+( SSH is a protocol for secure remote login and other secure network) s
+5 272 M
+( services over an insecure network. This document describes the SSH) s
+5 261 M
+( authentication protocol framework and public key, password, and) s
+5 250 M
+( host-based client authentication methods. Additional authentication) s
+5 239 M
+( methods are described in separate documents. The SSH authentication) s
+5 228 M
+( protocol runs on top of the SSH transport layer protocol and provides) s
+5 217 M
+( a single authenticated tunnel for the SSH connection protocol.) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 1]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 2 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+(Table of Contents) s
+5 668 M
+( 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 657 M
+( 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3) s
+5 646 M
+( 3. Conventions Used in This Document . . . . . . . . . . . . . 3) s
+5 635 M
+( 3.1 The Authentication Protocol Framework . . . . . . . . . . . 3) s
+5 624 M
+( 3.1.1 Authentication Requests . . . . . . . . . . . . . . . . . . 4) s
+5 613 M
+( 3.1.2 Responses to Authentication Requests . . . . . . . . . . . . 5) s
+5 602 M
+( 3.1.3 The "none" Authentication Request . . . . . . . . . . . . . 6) s
+5 591 M
+( 3.1.4 Completion of User Authentication . . . . . . . . . . . . . 6) s
+5 580 M
+( 3.1.5 Banner Message . . . . . . . . . . . . . . . . . . . . . . . 7) s
+5 569 M
+( 3.2 Authentication Protocol Message Numbers . . . . . . . . . . 7) s
+5 558 M
+( 3.3 Public Key Authentication Method: publickey . . . . . . . . 8) s
+5 547 M
+( 3.4 Password Authentication Method: password . . . . . . . . . . 10) s
+5 536 M
+( 3.5 Host-Based Authentication: hostbased . . . . . . . . . . . . 11) s
+5 525 M
+( 4. Security Considerations . . . . . . . . . . . . . . . . . . 12) s
+5 514 M
+( Normative . . . . . . . . . . . . . . . . . . . . . . . . . 13) s
+5 503 M
+( Informative . . . . . . . . . . . . . . . . . . . . . . . . 13) s
+5 492 M
+( Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 14) s
+5 481 M
+( Intellectual Property and Copyright Statements . . . . . . . 15) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 2]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (2,3) 2
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 3 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+(1. Contributors) s
+5 668 M
+( The major original contributors of this document were: Tatu Ylonen,) s
+5 657 M
+( Tero Kivinen, Timo J. Rinne, Sami Lehtinen \(all of SSH Communications) s
+5 646 M
+( Security Corp\), and Markku-Juhani O. Saarinen \(University of) s
+5 635 M
+( Jyvaskyla\)) s
+5 613 M
+( The document editor is: [email protected]. Comments on this) s
+5 602 M
+( internet draft should be sent to the IETF SECSH working group,) s
+5 591 M
+( details at: http://ietf.org/html.charters/secsh-charter.html) s
+5 569 M
+(2. Introduction) s
+5 547 M
+( The SSH authentication protocol is a general-purpose user) s
+5 536 M
+( authentication protocol. It is intended to be run over the SSH) s
+5 525 M
+( transport layer protocol [SSH-TRANS]. This protocol assumes that the) s
+5 514 M
+( underlying protocols provide integrity and confidentiality) s
+5 503 M
+( protection.) s
+5 481 M
+( This document should be read only after reading the SSH architecture) s
+5 470 M
+( document [SSH-ARCH]. This document freely uses terminology and) s
+5 459 M
+( notation from the architecture document without reference or further) s
+5 448 M
+( explanation.) s
+5 426 M
+( The service name for this protocol is "ssh-userauth".) s
+5 404 M
+( When this protocol starts, it receives the session identifier from) s
+5 393 M
+( the lower-level protocol \(this is the exchange hash H from the first) s
+5 382 M
+( key exchange\). The session identifier uniquely identifies this) s
+5 371 M
+( session and is suitable for signing in order to prove ownership of a) s
+5 360 M
+( private key. This protocol also needs to know whether the lower-level) s
+5 349 M
+( protocol provides confidentiality protection.) s
+5 327 M
+(3. Conventions Used in This Document) s
+5 305 M
+( The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",) s
+5 294 M
+( and "MAY" that appear in this document are to be interpreted as) s
+5 283 M
+( described in [RFC2119]) s
+5 261 M
+( The used data types and terminology are specified in the architecture) s
+5 250 M
+( document [SSH-ARCH]) s
+5 228 M
+( The architecture document also discusses the algorithm naming) s
+5 217 M
+( conventions that MUST be used with the SSH protocols.) s
+5 195 M
+(3.1 The Authentication Protocol Framework) s
+5 173 M
+( The server drives the authentication by telling the client which) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 3]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 4 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( authentication methods can be used to continue the exchange at any) s
+5 679 M
+( given time. The client has the freedom to try the methods listed by) s
+5 668 M
+( the server in any order. This gives the server complete control over) s
+5 657 M
+( the authentication process if desired, but also gives enough) s
+5 646 M
+( flexibility for the client to use the methods it supports or that are) s
+5 635 M
+( most convenient for the user, when multiple methods are offered by) s
+5 624 M
+( the server.) s
+5 602 M
+( Authentication methods are identified by their name, as defined in) s
+5 591 M
+( [SSH-ARCH]. The "none" method is reserved, and MUST NOT be listed as) s
+5 580 M
+( supported. However, it MAY be sent by the client. The server MUST) s
+5 569 M
+( always reject this request, unless the client is to be allowed in) s
+5 558 M
+( without any authentication, in which case the server MUST accept this) s
+5 547 M
+( request. The main purpose of sending this request is to get the list) s
+5 536 M
+( of supported methods from the server.) s
+5 514 M
+( The server SHOULD have a timeout for authentication, and disconnect) s
+5 503 M
+( if the authentication has not been accepted within the timeout) s
+5 492 M
+( period. The RECOMMENDED timeout period is 10 minutes. Additionally,) s
+5 481 M
+( the implementation SHOULD limit the number of failed authentication) s
+5 470 M
+( attempts a client may perform in a single session \(the RECOMMENDED) s
+5 459 M
+( limit is 20 attempts\). If the threshold is exceeded, the server) s
+5 448 M
+( SHOULD disconnect.) s
+5 426 M
+(3.1.1 Authentication Requests) s
+5 404 M
+( All authentication requests MUST use the following message format.) s
+5 393 M
+( Only the first few fields are defined; the remaining fields depend on) s
+5 382 M
+( the authentication method.) s
+5 360 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 349 M
+( string user name \(in ISO-10646 UTF-8 encoding [RFC2279]\)) s
+5 338 M
+( string service name \(in US-ASCII\)) s
+5 327 M
+( string method name \(US-ASCII\)) s
+5 316 M
+( The rest of the packet is method-specific.) s
+5 294 M
+( The user name and service are repeated in every new authentication) s
+5 283 M
+( attempt, and MAY change. The server implementation MUST carefully) s
+5 272 M
+( check them in every message, and MUST flush any accumulated) s
+5 261 M
+( authentication states if they change. If it is unable to flush some) s
+5 250 M
+( authentication state, it MUST disconnect if the user or service name) s
+5 239 M
+( changes.) s
+5 217 M
+( The service name specifies the service to start after authentication.) s
+5 206 M
+( There may be several different authenticated services provided. If) s
+5 195 M
+( the requested service is not available, the server MAY disconnect) s
+5 184 M
+( immediately or at any later time. Sending a proper disconnect) s
+5 173 M
+( message is RECOMMENDED. In any case, if the service does not exist,) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 4]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (4,5) 3
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 5 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( authentication MUST NOT be accepted.) s
+5 668 M
+( If the requested user does not exist, the server MAY disconnect, or) s
+5 657 M
+( MAY send a bogus list of acceptable authentication methods, but never) s
+5 646 M
+( accept any. This makes it possible for the server to avoid) s
+5 635 M
+( disclosing information on which accounts exist. In any case, if the) s
+5 624 M
+( user does not exist, the authentication request MUST NOT be accepted.) s
+5 602 M
+( While there is usually little point for clients to send requests that) s
+5 591 M
+( the server does not list as acceptable, sending such requests is not) s
+5 580 M
+( an error, and the server SHOULD simply reject requests that it does) s
+5 569 M
+( not recognize.) s
+5 547 M
+( An authentication request MAY result in a further exchange of) s
+5 536 M
+( messages. All such messages depend on the authentication method) s
+5 525 M
+( used, and the client MAY at any time continue with a new) s
+5 514 M
+( SSH_MSG_USERAUTH_REQUEST message, in which case the server MUST) s
+5 503 M
+( abandon the previous authentication attempt and continue with the new) s
+5 492 M
+( one.) s
+5 470 M
+(3.1.2 Responses to Authentication Requests) s
+5 448 M
+( If the server rejects the authentication request, it MUST respond) s
+5 437 M
+( with the following:) s
+5 415 M
+( byte SSH_MSG_USERAUTH_FAILURE) s
+5 404 M
+( string authentications that can continue) s
+5 393 M
+( boolean partial success) s
+5 371 M
+( "Authentications that can continue" is a comma-separated list of) s
+5 360 M
+( authentication method names that may productively continue the) s
+5 349 M
+( authentication dialog.) s
+5 327 M
+( It is RECOMMENDED that servers only include those methods in the list) s
+5 316 M
+( that are actually useful. However, it is not illegal to include) s
+5 305 M
+( methods that cannot be used to authenticate the user.) s
+5 283 M
+( Already successfully completed authentications SHOULD NOT be included) s
+5 272 M
+( in the list, unless they really should be performed again for some) s
+5 261 M
+( reason.) s
+5 239 M
+( "Partial success" MUST be TRUE if the authentication request to which) s
+5 228 M
+( this is a response was successful. It MUST be FALSE if the request) s
+5 217 M
+( was not successfully processed.) s
+5 195 M
+( When the server accepts authentication, it MUST respond with the) s
+5 184 M
+( following:) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 5]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 6 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( byte SSH_MSG_USERAUTH_SUCCESS) s
+5 668 M
+( Note that this is not sent after each step in a multi-method) s
+5 657 M
+( authentication sequence, but only when the authentication is) s
+5 646 M
+( complete.) s
+5 624 M
+( The client MAY send several authentication requests without waiting) s
+5 613 M
+( for responses from previous requests. The server MUST process each) s
+5 602 M
+( request completely and acknowledge any failed requests with a) s
+5 591 M
+( SSH_MSG_USERAUTH_FAILURE message before processing the next request.) s
+5 569 M
+( A request that results in further exchange of messages will be) s
+5 558 M
+( aborted by a second request. It is not possible to send a second) s
+5 547 M
+( request without waiting for a response from the server, if the first) s
+5 536 M
+( request will result in further exchange of messages. No) s
+5 525 M
+( SSH_MSG_USERAUTH_FAILURE message will be sent for the aborted method.) s
+5 503 M
+( SSH_MSG_USERAUTH_SUCCESS MUST be sent only once. When) s
+5 492 M
+( SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication) s
+5 481 M
+( requests received after that SHOULD be silently ignored.) s
+5 459 M
+( Any non-authentication messages sent by the client after the request) s
+5 448 M
+( that resulted in SSH_MSG_USERAUTH_SUCCESS being sent MUST be passed) s
+5 437 M
+( to the service being run on top of this protocol. Such messages can) s
+5 426 M
+( be identified by their message numbers \(see Section Message Numbers) s
+5 415 M
+( \(Section 3.2\)\).) s
+5 393 M
+(3.1.3 The "none" Authentication Request) s
+5 371 M
+( A client may request a list of authentication methods that may) s
+5 360 M
+( continue by using the "none" authentication method.) s
+5 338 M
+( If no authentication at all is needed for the user, the server MUST) s
+5 327 M
+( return SSH_MSG_USERAUTH_SUCCESS. Otherwise, the server MUST return) s
+5 316 M
+( SSH_MSG_USERAUTH_FAILURE and MAY return with it a list of) s
+5 305 M
+( authentication methods that can continue.) s
+5 283 M
+( This method MUST NOT be listed as supported by the server.) s
+5 261 M
+(3.1.4 Completion of User Authentication) s
+5 239 M
+( Authentication is complete when the server has responded with) s
+5 228 M
+( SSH_MSG_USERAUTH_SUCCESS; all authentication related messages) s
+5 217 M
+( received after sending this message SHOULD be silently ignored.) s
+5 195 M
+( After sending SSH_MSG_USERAUTH_SUCCESS, the server starts the) s
+5 184 M
+( requested service.) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 6]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (6,7) 4
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 7 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+(3.1.5 Banner Message) s
+5 668 M
+( In some jurisdictions, sending a warning message before) s
+5 657 M
+( authentication may be relevant for getting legal protection. Many) s
+5 646 M
+( UNIX machines, for example, normally display text from `/etc/issue',) s
+5 635 M
+( or use "tcp wrappers" or similar software to display a banner before) s
+5 624 M
+( issuing a login prompt.) s
+5 602 M
+( The SSH server may send a SSH_MSG_USERAUTH_BANNER message at any time) s
+5 591 M
+( before authentication is successful. This message contains text to) s
+5 580 M
+( be displayed to the client user before authentication is attempted.) s
+5 569 M
+( The format is as follows:) s
+5 547 M
+( byte SSH_MSG_USERAUTH_BANNER) s
+5 536 M
+( string message \(ISO-10646 UTF-8\)) s
+5 525 M
+( string language tag \(as defined in [RFC3066]\)) s
+5 503 M
+( The client SHOULD by default display the message on the screen.) s
+5 492 M
+( However, since the message is likely to be sent for every login) s
+5 481 M
+( attempt, and since some client software will need to open a separate) s
+5 470 M
+( window for this warning, the client software may allow the user to) s
+5 459 M
+( explicitly disable the display of banners from the server. The) s
+5 448 M
+( message may consist of multiple lines.) s
+5 426 M
+( If the message string is displayed, control character filtering) s
+5 415 M
+( discussed in [SSH-ARCH] SHOULD be used to avoid attacks by sending) s
+5 404 M
+( terminal control characters.) s
+5 382 M
+(3.2 Authentication Protocol Message Numbers) s
+5 360 M
+( All message numbers used by this authentication protocol are in the) s
+5 349 M
+( range from 50 to 79, which is part of the range reserved for) s
+5 338 M
+( protocols running on top of the SSH transport layer protocol.) s
+5 316 M
+( Message numbers of 80 and higher are reserved for protocols running) s
+5 305 M
+( after this authentication protocol, so receiving one of them before) s
+5 294 M
+( authentication is complete is an error, to which the server MUST) s
+5 283 M
+( respond by disconnecting \(preferably with a proper disconnect message) s
+5 272 M
+( sent first to ease troubleshooting\).) s
+5 250 M
+( After successful authentication, such messages are passed to the) s
+5 239 M
+( higher-level service.) s
+5 217 M
+( These are the general authentication message codes:) s
+5 195 M
+( #define SSH_MSG_USERAUTH_REQUEST 50) s
+5 184 M
+( #define SSH_MSG_USERAUTH_FAILURE 51) s
+5 173 M
+( #define SSH_MSG_USERAUTH_SUCCESS 52) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 7]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 8 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( #define SSH_MSG_USERAUTH_BANNER 53) s
+5 668 M
+( In addition to the above, there is a range of message numbers) s
+5 657 M
+( \(60..79\) reserved for method-specific messages. These messages are) s
+5 646 M
+( only sent by the server \(client sends only SSH_MSG_USERAUTH_REQUEST) s
+5 635 M
+( messages\). Different authentication methods reuse the same message) s
+5 624 M
+( numbers.) s
+5 602 M
+(3.3 Public Key Authentication Method: publickey) s
+5 580 M
+( The only REQUIRED authentication method is public key authentication.) s
+5 569 M
+( All implementations MUST support this method; however, not all users) s
+5 558 M
+( need to have public keys, and most local policies are not likely to) s
+5 547 M
+( require public key authentication for all users in the near future.) s
+5 525 M
+( With this method, the possession of a private key serves as) s
+5 514 M
+( authentication. This method works by sending a signature created) s
+5 503 M
+( with a private key of the user. The server MUST check that the key) s
+5 492 M
+( is a valid authenticator for the user, and MUST check that the) s
+5 481 M
+( signature is valid. If both hold, the authentication request MUST be) s
+5 470 M
+( accepted; otherwise it MUST be rejected. \(Note that the server MAY) s
+5 459 M
+( require additional authentications after successful authentication.\)) s
+5 437 M
+( Private keys are often stored in an encrypted form at the client) s
+5 426 M
+( host, and the user must supply a passphrase before the signature can) s
+5 415 M
+( be generated. Even if they are not, the signing operation involves) s
+5 404 M
+( some expensive computation. To avoid unnecessary processing and user) s
+5 393 M
+( interaction, the following message is provided for querying whether) s
+5 382 M
+( authentication using the key would be acceptable.) s
+5 360 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 349 M
+( string user name) s
+5 338 M
+( string service) s
+5 327 M
+( string "publickey") s
+5 316 M
+( boolean FALSE) s
+5 305 M
+( string public key algorithm name) s
+5 294 M
+( string public key blob) s
+5 272 M
+( Public key algorithms are defined in the transport layer) s
+5 261 M
+( specification [SSH-TRANS]. The public key blob may contain) s
+5 250 M
+( certificates.) s
+5 228 M
+( Any public key algorithm may be offered for use in authentication.) s
+5 217 M
+( In particular, the list is not constrained by what was negotiated) s
+5 206 M
+( during key exchange. If the server does not support some algorithm,) s
+5 195 M
+( it MUST simply reject the request.) s
+5 173 M
+( The server MUST respond to this message with either) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 8]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (8,9) 5
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 9 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( SSH_MSG_USERAUTH_FAILURE or with the following:) s
+5 668 M
+( byte SSH_MSG_USERAUTH_PK_OK) s
+5 657 M
+( string public key algorithm name from the request) s
+5 646 M
+( string public key blob from the request) s
+5 624 M
+( To perform actual authentication, the client MAY then send a) s
+5 613 M
+( signature generated using the private key. The client MAY send the) s
+5 602 M
+( signature directly without first verifying whether the key is) s
+5 591 M
+( acceptable. The signature is sent using the following packet:) s
+5 569 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 558 M
+( string user name) s
+5 547 M
+( string service) s
+5 536 M
+( string "publickey") s
+5 525 M
+( boolean TRUE) s
+5 514 M
+( string public key algorithm name) s
+5 503 M
+( string public key to be used for authentication) s
+5 492 M
+( string signature) s
+5 470 M
+( Signature is a signature by the corresponding private key over the) s
+5 459 M
+( following data, in the following order:) s
+5 437 M
+( string session identifier) s
+5 426 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 415 M
+( string user name) s
+5 404 M
+( string service) s
+5 393 M
+( string "publickey") s
+5 382 M
+( boolean TRUE) s
+5 371 M
+( string public key algorithm name) s
+5 360 M
+( string public key to be used for authentication) s
+5 338 M
+( When the server receives this message, it MUST check whether the) s
+5 327 M
+( supplied key is acceptable for authentication, and if so, it MUST) s
+5 316 M
+( check whether the signature is correct.) s
+5 294 M
+( If both checks succeed, this method is successful. Note that the) s
+5 283 M
+( server may require additional authentications. The server MUST) s
+5 272 M
+( respond with SSH_MSG_USERAUTH_SUCCESS \(if no more authentications are) s
+5 261 M
+( needed\), or SSH_MSG_USERAUTH_FAILURE \(if the request failed, or more) s
+5 250 M
+( authentications are needed\).) s
+5 228 M
+( The following method-specific message numbers are used by the) s
+5 217 M
+( publickey authentication method.) s
+5 195 M
+( /* Key-based */) s
+5 184 M
+( #define SSH_MSG_USERAUTH_PK_OK 60) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 9]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 10 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+(3.4 Password Authentication Method: password) s
+5 668 M
+( Password authentication uses the following packets. Note that a) s
+5 657 M
+( server MAY request the user to change the password. All) s
+5 646 M
+( implementations SHOULD support password authentication.) s
+5 624 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 613 M
+( string user name) s
+5 602 M
+( string service) s
+5 591 M
+( string "password") s
+5 580 M
+( boolean FALSE) s
+5 569 M
+( string plaintext password \(ISO-10646 UTF-8\)) s
+5 547 M
+( Note that the password is encoded in ISO-10646 UTF-8. It is up to) s
+5 536 M
+( the server how it interprets the password and validates it against) s
+5 525 M
+( the password database. However, if the client reads the password in) s
+5 514 M
+( some other encoding \(e.g., ISO 8859-1 \(ISO Latin1\)\), it MUST convert) s
+5 503 M
+( the password to ISO-10646 UTF-8 before transmitting, and the server) s
+5 492 M
+( MUST convert the password to the encoding used on that system for) s
+5 481 M
+( passwords.) s
+5 459 M
+( Note that even though the cleartext password is transmitted in the) s
+5 448 M
+( packet, the entire packet is encrypted by the transport layer. Both) s
+5 437 M
+( the server and the client should check whether the underlying) s
+5 426 M
+( transport layer provides confidentiality \(i.e., if encryption is) s
+5 415 M
+( being used\). If no confidentiality is provided \(none cipher\),) s
+5 404 M
+( password authentication SHOULD be disabled. If there is no) s
+5 393 M
+( confidentiality or no MAC, password change SHOULD be disabled.) s
+5 371 M
+( Normally, the server responds to this message with success or) s
+5 360 M
+( failure. However, if the password has expired the server SHOULD) s
+5 349 M
+( indicate this by responding with SSH_MSG_USERAUTH_PASSWD_CHANGEREQ.) s
+5 338 M
+( In anycase the server MUST NOT allow an expired password to be used) s
+5 327 M
+( for authentication.) s
+5 305 M
+( byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) s
+5 294 M
+( string prompt \(ISO-10646 UTF-8\)) s
+5 283 M
+( string language tag \(as defined in [RFC3066]\)) s
+5 261 M
+( In this case, the client MAY continue with a different authentication) s
+5 250 M
+( method, or request a new password from the user and retry password) s
+5 239 M
+( authentication using the following message. The client MAY also send) s
+5 228 M
+( this message instead of the normal password authentication request) s
+5 217 M
+( without the server asking for it.) s
+5 195 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 184 M
+( string user name) s
+5 173 M
+( string service) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 10]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (10,11) 6
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 11 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( string "password") s
+5 679 M
+( boolean TRUE) s
+5 668 M
+( string plaintext old password \(ISO-10646 UTF-8\)) s
+5 657 M
+( string plaintext new password \(ISO-10646 UTF-8\)) s
+5 635 M
+( The server must reply to request message with) s
+5 624 M
+( SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another) s
+5 613 M
+( SSH_MSG_USERAUTH_PASSWD_CHANGEREQ. The meaning of these is as) s
+5 602 M
+( follows:) s
+5 580 M
+( SSH_MSG_USERAUTH_SUCCESS The password has been changed, and) s
+5 569 M
+( authentication has been successfully completed.) s
+5 547 M
+( SSH_MSG_USERAUTH_FAILURE with partial success The password has) s
+5 536 M
+( been changed, but more authentications are needed.) s
+5 514 M
+( SSH_MSG_USERAUTH_FAILURE without partial success The password has) s
+5 503 M
+( not been changed. Either password changing was not supported, or) s
+5 492 M
+( the old password was bad. Note that if the server has already) s
+5 481 M
+( sent SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, we know that it supports) s
+5 470 M
+( changing the password.) s
+5 448 M
+( SSH_MSG_USERAUTH_CHANGEREQ The password was not changed because) s
+5 437 M
+( the new password was not acceptable \(e.g. too easy to guess\).) s
+5 415 M
+( The following method-specific message numbers are used by the) s
+5 404 M
+( password authentication method.) s
+5 382 M
+( #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60) s
+5 349 M
+(3.5 Host-Based Authentication: hostbased) s
+5 327 M
+( Some sites wish to allow authentication based on the host where the) s
+5 316 M
+( user is coming from, and the user name on the remote host. While) s
+5 305 M
+( this form of authentication is not suitable for high-security sites,) s
+5 294 M
+( it can be very convenient in many environments. This form of) s
+5 283 M
+( authentication is OPTIONAL. When used, special care SHOULD be taken) s
+5 272 M
+( to prevent a regular user from obtaining the private host key.) s
+5 250 M
+( The client requests this form of authentication by sending the) s
+5 239 M
+( following message. It is similar to the UNIX "rhosts" and) s
+5 228 M
+( "hosts.equiv" styles of authentication, except that the identity of) s
+5 217 M
+( the client host is checked more rigorously.) s
+5 195 M
+( This method works by having the client send a signature created with) s
+5 184 M
+( the private key of the client host, which the server checks with that) s
+5 173 M
+( host's public key. Once the client host's identity is established,) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 11]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 12 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( authorization \(but no further authentication\) is performed based on) s
+5 679 M
+( the user names on the server and the client, and the client host) s
+5 668 M
+( name.) s
+5 646 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 635 M
+( string user name) s
+5 624 M
+( string service) s
+5 613 M
+( string "hostbased") s
+5 602 M
+( string public key algorithm for host key) s
+5 591 M
+( string public host key and certificates for client host) s
+5 580 M
+( string client host name \(FQDN; US-ASCII\)) s
+5 569 M
+( string user name on the client host \(ISO-10646 UTF-8\)) s
+5 558 M
+( string signature) s
+5 536 M
+( Public key algorithm names for use in "public key algorithm for host) s
+5 525 M
+( key" are defined in the transport layer specification. The "public) s
+5 514 M
+( host key for client host" may include certificates.) s
+5 492 M
+( Signature is a signature with the private host key of the following) s
+5 481 M
+( data, in this order:) s
+5 459 M
+( string session identifier) s
+5 448 M
+( byte SSH_MSG_USERAUTH_REQUEST) s
+5 437 M
+( string user name) s
+5 426 M
+( string service) s
+5 415 M
+( string "hostbased") s
+5 404 M
+( string public key algorithm for host key) s
+5 393 M
+( string public host key and certificates for client host) s
+5 382 M
+( string client host name \(FQDN; US-ASCII\)) s
+5 371 M
+( string user name on the client host\(ISO-10646 UTF-8\)) s
+5 349 M
+( The server MUST verify that the host key actually belongs to the) s
+5 338 M
+( client host named in the message, that the given user on that host is) s
+5 327 M
+( allowed to log in, and that the signature is a valid signature on the) s
+5 316 M
+( appropriate value by the given host key. The server MAY ignore the) s
+5 305 M
+( client user name, if it wants to authenticate only the client host.) s
+5 283 M
+( It is RECOMMENDED that whenever possible, the server perform) s
+5 272 M
+( additional checks to verify that the network address obtained from) s
+5 261 M
+( the \(untrusted\) network matches the given client host name. This) s
+5 250 M
+( makes exploiting compromised host keys more difficult. Note that) s
+5 239 M
+( this may require special handling for connections coming through a) s
+5 228 M
+( firewall.) s
+5 206 M
+(4. Security Considerations) s
+5 184 M
+( The purpose of this protocol is to perform client user) s
+5 173 M
+( authentication. It assumed that this runs over a secure transport) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 12]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (12,13) 7
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 13 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( layer protocol, which has already authenticated the server machine,) s
+5 679 M
+( established an encrypted communications channel, and computed a) s
+5 668 M
+( unique session identifier for this session. The transport layer) s
+5 657 M
+( provides forward secrecy for password authentication and other) s
+5 646 M
+( methods that rely on secret data.) s
+5 624 M
+( Full security considerations for this protocol are provided in) s
+5 613 M
+( Section 8 of [SSH-ARCH]) s
+5 591 M
+(Normative) s
+5 569 M
+( [SSH-ARCH]) s
+5 558 M
+( Ylonen, T., "SSH Protocol Architecture", I-D) s
+5 547 M
+( draft-ietf-architecture-15.txt, Oct 2003.) s
+5 525 M
+( [SSH-TRANS]) s
+5 514 M
+( Ylonen, T., "SSH Transport Layer Protocol", I-D) s
+5 503 M
+( draft-ietf-transport-17.txt, Oct 2003.) s
+5 481 M
+( [SSH-USERAUTH]) s
+5 470 M
+( Ylonen, T., "SSH Authentication Protocol", I-D) s
+5 459 M
+( draft-ietf-userauth-18.txt, Oct 2003.) s
+5 437 M
+( [SSH-CONNECT]) s
+5 426 M
+( Ylonen, T., "SSH Connection Protocol", I-D) s
+5 415 M
+( draft-ietf-connect-18.txt, Oct 2003.) s
+5 393 M
+( [SSH-NUMBERS]) s
+5 382 M
+( Lehtinen, S. and D. Moffat, "SSH Protocol Assigned) s
+5 371 M
+( Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct) s
+5 360 M
+( 2003.) s
+5 338 M
+( [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate) s
+5 327 M
+( Requirement Levels", BCP 14, RFC 2119, March 1997.) s
+5 305 M
+(Informative) s
+5 283 M
+( [RFC3066] Alvestrand, H., "Tags for the Identification of) s
+5 272 M
+( Languages", BCP 47, RFC 3066, January 2001.) s
+5 250 M
+( [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO) s
+5 239 M
+( 10646", RFC 2279, January 1998.) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 13]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 14 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+(Authors' Addresses) s
+5 668 M
+( Tatu Ylonen) s
+5 657 M
+( SSH Communications Security Corp) s
+5 646 M
+( Fredrikinkatu 42) s
+5 635 M
+( HELSINKI FIN-00100) s
+5 624 M
+( Finland) s
+5 602 M
+( EMail: [email protected]) s
+5 569 M
+( Darren J. Moffat \(editor\)) s
+5 558 M
+( Sun Microsystems, Inc) s
+5 547 M
+( 17 Network Circle) s
+5 536 M
+( Menlo Park 95025) s
+5 525 M
+( USA) s
+5 503 M
+( EMail: [email protected]) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 14]) s
+_R
+S
+PStoPSsaved restore
+%%Page: (14,15) 8
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 0.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+/showpage{}def/copypage{}def/erasepage{}def
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 15 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+(Intellectual Property Statement) s
+5 668 M
+( The IETF takes no position regarding the validity or scope of any) s
+5 657 M
+( intellectual property or other rights that might be claimed to) s
+5 646 M
+( pertain to the implementation or use of the technology described in) s
+5 635 M
+( this document or the extent to which any license under such rights) s
+5 624 M
+( might or might not be available; neither does it represent that it) s
+5 613 M
+( has made any effort to identify any such rights. Information on the) s
+5 602 M
+( IETF's procedures with respect to rights in standards-track and) s
+5 591 M
+( standards-related documentation can be found in BCP-11. Copies of) s
+5 580 M
+( claims of rights made available for publication and any assurances of) s
+5 569 M
+( licenses to be made available, or the result of an attempt made to) s
+5 558 M
+( obtain a general license or permission for the use of such) s
+5 547 M
+( proprietary rights by implementors or users of this specification can) s
+5 536 M
+( be obtained from the IETF Secretariat.) s
+5 514 M
+( The IETF invites any interested party to bring to its attention any) s
+5 503 M
+( copyrights, patents or patent applications, or other proprietary) s
+5 492 M
+( rights which may cover technology that may be required to practice) s
+5 481 M
+( this standard. Please address the information to the IETF Executive) s
+5 470 M
+( Director.) s
+5 448 M
+( The IETF has been notified of intellectual property rights claimed in) s
+5 437 M
+( regard to some or all of the specification contained in this) s
+5 426 M
+( document. For more information consult the online list of claimed) s
+5 415 M
+( rights.) s
+5 382 M
+(Full Copyright Statement) s
+5 360 M
+( Copyright \(C\) The Internet Society \(2002\). All Rights Reserved.) s
+5 338 M
+( This document and translations of it may be copied and furnished to) s
+5 327 M
+( others, and derivative works that comment on or otherwise explain it) s
+5 316 M
+( or assist in its implementation may be prepared, copied, published) s
+5 305 M
+( and distributed, in whole or in part, without restriction of any) s
+5 294 M
+( kind, provided that the above copyright notice and this paragraph are) s
+5 283 M
+( included on all such copies and derivative works. However, this) s
+5 272 M
+( document itself may not be modified in any way, such as by removing) s
+5 261 M
+( the copyright notice or references to the Internet Society or other) s
+5 250 M
+( Internet organizations, except as needed for the purpose of) s
+5 239 M
+( developing Internet standards in which case the procedures for) s
+5 228 M
+( copyrights defined in the Internet Standards process must be) s
+5 217 M
+( followed, or as required to translate it into languages other than) s
+5 206 M
+( English.) s
+5 184 M
+( The limited permissions granted above are perpetual and will not be) s
+5 173 M
+( revoked by the Internet Society or its successors or assignees.) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 15]) s
+_R
+S
+PStoPSsaved restore
+userdict/PStoPSsaved save put
+PStoPSmatrix setmatrix
+595.000000 421.271378 translate
+90 rotate
+0.706651 dup scale
+userdict/PStoPSmatrix matrix currentmatrix put
+userdict/PStoPSclip{0 0 moveto
+ 595.000000 0 rlineto 0 842.000000 rlineto -595.000000 0 rlineto
+ closepath}put initclip
+PStoPSxform concat
+%%BeginPageSetup
+_S
+75 0 translate
+/pagenum 16 def
+/fname () def
+/fdir () def
+/ftail () def
+/user_header_p false def
+%%EndPageSetup
+5 723 M
+(Internet-Draft SSH Authentication Protocol September 2002) s
+5 690 M
+( This document and the information contained herein is provided on an) s
+5 679 M
+( "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING) s
+5 668 M
+( TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING) s
+5 657 M
+( BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION) s
+5 646 M
+( HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF) s
+5 635 M
+( MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.) s
+5 602 M
+(Acknowledgment) s
+5 580 M
+( Funding for the RFC Editor function is currently provided by the) s
+5 569 M
+( Internet Society.) s
+5 129 M
+(Ylonen & Moffat Expires March 2, 2003 [Page 16]) s
+_R
+S
+PStoPSsaved restore
+%%Trailer
+%%Pages: 16
+%%DocumentNeededResources: font Courier-Bold Courier
+%%EOF
diff --git a/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt
new file mode 100644
index 0000000000..9dae578a35
--- /dev/null
+++ b/lib/ssh/doc/standard/draft-ietf-secsh-userauth-18.txt
@@ -0,0 +1,896 @@
+
+
+
+Network Working Group T. Ylonen
+Internet-Draft SSH Communications Security Corp
+Expires: March 2, 2003 D. Moffat, Ed.
+ Sun Microsystems, Inc
+ September 2002
+
+
+ SSH Authentication Protocol
+ draft-ietf-secsh-userauth-18.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that other
+ groups may also distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on March 2, 2003.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ SSH is a protocol for secure remote login and other secure network
+ services over an insecure network. This document describes the SSH
+ authentication protocol framework and public key, password, and
+ host-based client authentication methods. Additional authentication
+ methods are described in separate documents. The SSH authentication
+ protocol runs on top of the SSH transport layer protocol and provides
+ a single authenticated tunnel for the SSH connection protocol.
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 1]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+Table of Contents
+
+ 1. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Conventions Used in This Document . . . . . . . . . . . . . 3
+ 3.1 The Authentication Protocol Framework . . . . . . . . . . . 3
+ 3.1.1 Authentication Requests . . . . . . . . . . . . . . . . . . 4
+ 3.1.2 Responses to Authentication Requests . . . . . . . . . . . . 5
+ 3.1.3 The "none" Authentication Request . . . . . . . . . . . . . 6
+ 3.1.4 Completion of User Authentication . . . . . . . . . . . . . 6
+ 3.1.5 Banner Message . . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.2 Authentication Protocol Message Numbers . . . . . . . . . . 7
+ 3.3 Public Key Authentication Method: publickey . . . . . . . . 8
+ 3.4 Password Authentication Method: password . . . . . . . . . . 10
+ 3.5 Host-Based Authentication: hostbased . . . . . . . . . . . . 11
+ 4. Security Considerations . . . . . . . . . . . . . . . . . . 12
+ Normative . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ Informative . . . . . . . . . . . . . . . . . . . . . . . . 13
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 14
+ Intellectual Property and Copyright Statements . . . . . . . 15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 2]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+1. Contributors
+
+ The major original contributors of this document were: Tatu Ylonen,
+ Tero Kivinen, Timo J. Rinne, Sami Lehtinen (all of SSH Communications
+ Security Corp), and Markku-Juhani O. Saarinen (University of
+ Jyvaskyla)
+
+ The document editor is: [email protected]. Comments on this
+ internet draft should be sent to the IETF SECSH working group,
+ details at: http://ietf.org/html.charters/secsh-charter.html
+
+2. Introduction
+
+ The SSH authentication protocol is a general-purpose user
+ authentication protocol. It is intended to be run over the SSH
+ transport layer protocol [SSH-TRANS]. This protocol assumes that the
+ underlying protocols provide integrity and confidentiality
+ protection.
+
+ This document should be read only after reading the SSH architecture
+ document [SSH-ARCH]. This document freely uses terminology and
+ notation from the architecture document without reference or further
+ explanation.
+
+ The service name for this protocol is "ssh-userauth".
+
+ When this protocol starts, it receives the session identifier from
+ the lower-level protocol (this is the exchange hash H from the first
+ key exchange). The session identifier uniquely identifies this
+ session and is suitable for signing in order to prove ownership of a
+ private key. This protocol also needs to know whether the lower-level
+ protocol provides confidentiality protection.
+
+3. Conventions Used in This Document
+
+ The keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ and "MAY" that appear in this document are to be interpreted as
+ described in [RFC2119]
+
+ The used data types and terminology are specified in the architecture
+ document [SSH-ARCH]
+
+ The architecture document also discusses the algorithm naming
+ conventions that MUST be used with the SSH protocols.
+
+3.1 The Authentication Protocol Framework
+
+ The server drives the authentication by telling the client which
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 3]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ authentication methods can be used to continue the exchange at any
+ given time. The client has the freedom to try the methods listed by
+ the server in any order. This gives the server complete control over
+ the authentication process if desired, but also gives enough
+ flexibility for the client to use the methods it supports or that are
+ most convenient for the user, when multiple methods are offered by
+ the server.
+
+ Authentication methods are identified by their name, as defined in
+ [SSH-ARCH]. The "none" method is reserved, and MUST NOT be listed as
+ supported. However, it MAY be sent by the client. The server MUST
+ always reject this request, unless the client is to be allowed in
+ without any authentication, in which case the server MUST accept this
+ request. The main purpose of sending this request is to get the list
+ of supported methods from the server.
+
+ The server SHOULD have a timeout for authentication, and disconnect
+ if the authentication has not been accepted within the timeout
+ period. The RECOMMENDED timeout period is 10 minutes. Additionally,
+ the implementation SHOULD limit the number of failed authentication
+ attempts a client may perform in a single session (the RECOMMENDED
+ limit is 20 attempts). If the threshold is exceeded, the server
+ SHOULD disconnect.
+
+3.1.1 Authentication Requests
+
+ All authentication requests MUST use the following message format.
+ Only the first few fields are defined; the remaining fields depend on
+ the authentication method.
+
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name (in ISO-10646 UTF-8 encoding [RFC2279])
+ string service name (in US-ASCII)
+ string method name (US-ASCII)
+ The rest of the packet is method-specific.
+
+ The user name and service are repeated in every new authentication
+ attempt, and MAY change. The server implementation MUST carefully
+ check them in every message, and MUST flush any accumulated
+ authentication states if they change. If it is unable to flush some
+ authentication state, it MUST disconnect if the user or service name
+ changes.
+
+ The service name specifies the service to start after authentication.
+ There may be several different authenticated services provided. If
+ the requested service is not available, the server MAY disconnect
+ immediately or at any later time. Sending a proper disconnect
+ message is RECOMMENDED. In any case, if the service does not exist,
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 4]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ authentication MUST NOT be accepted.
+
+ If the requested user does not exist, the server MAY disconnect, or
+ MAY send a bogus list of acceptable authentication methods, but never
+ accept any. This makes it possible for the server to avoid
+ disclosing information on which accounts exist. In any case, if the
+ user does not exist, the authentication request MUST NOT be accepted.
+
+ While there is usually little point for clients to send requests that
+ the server does not list as acceptable, sending such requests is not
+ an error, and the server SHOULD simply reject requests that it does
+ not recognize.
+
+ An authentication request MAY result in a further exchange of
+ messages. All such messages depend on the authentication method
+ used, and the client MAY at any time continue with a new
+ SSH_MSG_USERAUTH_REQUEST message, in which case the server MUST
+ abandon the previous authentication attempt and continue with the new
+ one.
+
+3.1.2 Responses to Authentication Requests
+
+ If the server rejects the authentication request, it MUST respond
+ with the following:
+
+ byte SSH_MSG_USERAUTH_FAILURE
+ string authentications that can continue
+ boolean partial success
+
+ "Authentications that can continue" is a comma-separated list of
+ authentication method names that may productively continue the
+ authentication dialog.
+
+ It is RECOMMENDED that servers only include those methods in the list
+ that are actually useful. However, it is not illegal to include
+ methods that cannot be used to authenticate the user.
+
+ Already successfully completed authentications SHOULD NOT be included
+ in the list, unless they really should be performed again for some
+ reason.
+
+ "Partial success" MUST be TRUE if the authentication request to which
+ this is a response was successful. It MUST be FALSE if the request
+ was not successfully processed.
+
+ When the server accepts authentication, it MUST respond with the
+ following:
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 5]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ byte SSH_MSG_USERAUTH_SUCCESS
+
+ Note that this is not sent after each step in a multi-method
+ authentication sequence, but only when the authentication is
+ complete.
+
+ The client MAY send several authentication requests without waiting
+ for responses from previous requests. The server MUST process each
+ request completely and acknowledge any failed requests with a
+ SSH_MSG_USERAUTH_FAILURE message before processing the next request.
+
+ A request that results in further exchange of messages will be
+ aborted by a second request. It is not possible to send a second
+ request without waiting for a response from the server, if the first
+ request will result in further exchange of messages. No
+ SSH_MSG_USERAUTH_FAILURE message will be sent for the aborted method.
+
+ SSH_MSG_USERAUTH_SUCCESS MUST be sent only once. When
+ SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication
+ requests received after that SHOULD be silently ignored.
+
+ Any non-authentication messages sent by the client after the request
+ that resulted in SSH_MSG_USERAUTH_SUCCESS being sent MUST be passed
+ to the service being run on top of this protocol. Such messages can
+ be identified by their message numbers (see Section Message Numbers
+ (Section 3.2)).
+
+3.1.3 The "none" Authentication Request
+
+ A client may request a list of authentication methods that may
+ continue by using the "none" authentication method.
+
+ If no authentication at all is needed for the user, the server MUST
+ return SSH_MSG_USERAUTH_SUCCESS. Otherwise, the server MUST return
+ SSH_MSG_USERAUTH_FAILURE and MAY return with it a list of
+ authentication methods that can continue.
+
+ This method MUST NOT be listed as supported by the server.
+
+3.1.4 Completion of User Authentication
+
+ Authentication is complete when the server has responded with
+ SSH_MSG_USERAUTH_SUCCESS; all authentication related messages
+ received after sending this message SHOULD be silently ignored.
+
+ After sending SSH_MSG_USERAUTH_SUCCESS, the server starts the
+ requested service.
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 6]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+3.1.5 Banner Message
+
+ In some jurisdictions, sending a warning message before
+ authentication may be relevant for getting legal protection. Many
+ UNIX machines, for example, normally display text from `/etc/issue',
+ or use "tcp wrappers" or similar software to display a banner before
+ issuing a login prompt.
+
+ The SSH server may send a SSH_MSG_USERAUTH_BANNER message at any time
+ before authentication is successful. This message contains text to
+ be displayed to the client user before authentication is attempted.
+ The format is as follows:
+
+ byte SSH_MSG_USERAUTH_BANNER
+ string message (ISO-10646 UTF-8)
+ string language tag (as defined in [RFC3066])
+
+ The client SHOULD by default display the message on the screen.
+ However, since the message is likely to be sent for every login
+ attempt, and since some client software will need to open a separate
+ window for this warning, the client software may allow the user to
+ explicitly disable the display of banners from the server. The
+ message may consist of multiple lines.
+
+ If the message string is displayed, control character filtering
+ discussed in [SSH-ARCH] SHOULD be used to avoid attacks by sending
+ terminal control characters.
+
+3.2 Authentication Protocol Message Numbers
+
+ All message numbers used by this authentication protocol are in the
+ range from 50 to 79, which is part of the range reserved for
+ protocols running on top of the SSH transport layer protocol.
+
+ Message numbers of 80 and higher are reserved for protocols running
+ after this authentication protocol, so receiving one of them before
+ authentication is complete is an error, to which the server MUST
+ respond by disconnecting (preferably with a proper disconnect message
+ sent first to ease troubleshooting).
+
+ After successful authentication, such messages are passed to the
+ higher-level service.
+
+ These are the general authentication message codes:
+
+ #define SSH_MSG_USERAUTH_REQUEST 50
+ #define SSH_MSG_USERAUTH_FAILURE 51
+ #define SSH_MSG_USERAUTH_SUCCESS 52
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 7]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ #define SSH_MSG_USERAUTH_BANNER 53
+
+ In addition to the above, there is a range of message numbers
+ (60..79) reserved for method-specific messages. These messages are
+ only sent by the server (client sends only SSH_MSG_USERAUTH_REQUEST
+ messages). Different authentication methods reuse the same message
+ numbers.
+
+3.3 Public Key Authentication Method: publickey
+
+ The only REQUIRED authentication method is public key authentication.
+ All implementations MUST support this method; however, not all users
+ need to have public keys, and most local policies are not likely to
+ require public key authentication for all users in the near future.
+
+ With this method, the possession of a private key serves as
+ authentication. This method works by sending a signature created
+ with a private key of the user. The server MUST check that the key
+ is a valid authenticator for the user, and MUST check that the
+ signature is valid. If both hold, the authentication request MUST be
+ accepted; otherwise it MUST be rejected. (Note that the server MAY
+ require additional authentications after successful authentication.)
+
+ Private keys are often stored in an encrypted form at the client
+ host, and the user must supply a passphrase before the signature can
+ be generated. Even if they are not, the signing operation involves
+ some expensive computation. To avoid unnecessary processing and user
+ interaction, the following message is provided for querying whether
+ authentication using the key would be acceptable.
+
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name
+ string service
+ string "publickey"
+ boolean FALSE
+ string public key algorithm name
+ string public key blob
+
+ Public key algorithms are defined in the transport layer
+ specification [SSH-TRANS]. The public key blob may contain
+ certificates.
+
+ Any public key algorithm may be offered for use in authentication.
+ In particular, the list is not constrained by what was negotiated
+ during key exchange. If the server does not support some algorithm,
+ it MUST simply reject the request.
+
+ The server MUST respond to this message with either
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 8]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ SSH_MSG_USERAUTH_FAILURE or with the following:
+
+ byte SSH_MSG_USERAUTH_PK_OK
+ string public key algorithm name from the request
+ string public key blob from the request
+
+ To perform actual authentication, the client MAY then send a
+ signature generated using the private key. The client MAY send the
+ signature directly without first verifying whether the key is
+ acceptable. The signature is sent using the following packet:
+
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name
+ string service
+ string "publickey"
+ boolean TRUE
+ string public key algorithm name
+ string public key to be used for authentication
+ string signature
+
+ Signature is a signature by the corresponding private key over the
+ following data, in the following order:
+
+ string session identifier
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name
+ string service
+ string "publickey"
+ boolean TRUE
+ string public key algorithm name
+ string public key to be used for authentication
+
+ When the server receives this message, it MUST check whether the
+ supplied key is acceptable for authentication, and if so, it MUST
+ check whether the signature is correct.
+
+ If both checks succeed, this method is successful. Note that the
+ server may require additional authentications. The server MUST
+ respond with SSH_MSG_USERAUTH_SUCCESS (if no more authentications are
+ needed), or SSH_MSG_USERAUTH_FAILURE (if the request failed, or more
+ authentications are needed).
+
+ The following method-specific message numbers are used by the
+ publickey authentication method.
+
+ /* Key-based */
+ #define SSH_MSG_USERAUTH_PK_OK 60
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 9]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+3.4 Password Authentication Method: password
+
+ Password authentication uses the following packets. Note that a
+ server MAY request the user to change the password. All
+ implementations SHOULD support password authentication.
+
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name
+ string service
+ string "password"
+ boolean FALSE
+ string plaintext password (ISO-10646 UTF-8)
+
+ Note that the password is encoded in ISO-10646 UTF-8. It is up to
+ the server how it interprets the password and validates it against
+ the password database. However, if the client reads the password in
+ some other encoding (e.g., ISO 8859-1 (ISO Latin1)), it MUST convert
+ the password to ISO-10646 UTF-8 before transmitting, and the server
+ MUST convert the password to the encoding used on that system for
+ passwords.
+
+ Note that even though the cleartext password is transmitted in the
+ packet, the entire packet is encrypted by the transport layer. Both
+ the server and the client should check whether the underlying
+ transport layer provides confidentiality (i.e., if encryption is
+ being used). If no confidentiality is provided (none cipher),
+ password authentication SHOULD be disabled. If there is no
+ confidentiality or no MAC, password change SHOULD be disabled.
+
+ Normally, the server responds to this message with success or
+ failure. However, if the password has expired the server SHOULD
+ indicate this by responding with SSH_MSG_USERAUTH_PASSWD_CHANGEREQ.
+ In anycase the server MUST NOT allow an expired password to be used
+ for authentication.
+
+ byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
+ string prompt (ISO-10646 UTF-8)
+ string language tag (as defined in [RFC3066])
+
+ In this case, the client MAY continue with a different authentication
+ method, or request a new password from the user and retry password
+ authentication using the following message. The client MAY also send
+ this message instead of the normal password authentication request
+ without the server asking for it.
+
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name
+ string service
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 10]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ string "password"
+ boolean TRUE
+ string plaintext old password (ISO-10646 UTF-8)
+ string plaintext new password (ISO-10646 UTF-8)
+
+ The server must reply to request message with
+ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another
+ SSH_MSG_USERAUTH_PASSWD_CHANGEREQ. The meaning of these is as
+ follows:
+
+ SSH_MSG_USERAUTH_SUCCESS The password has been changed, and
+ authentication has been successfully completed.
+
+ SSH_MSG_USERAUTH_FAILURE with partial success The password has
+ been changed, but more authentications are needed.
+
+ SSH_MSG_USERAUTH_FAILURE without partial success The password has
+ not been changed. Either password changing was not supported, or
+ the old password was bad. Note that if the server has already
+ sent SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, we know that it supports
+ changing the password.
+
+ SSH_MSG_USERAUTH_CHANGEREQ The password was not changed because
+ the new password was not acceptable (e.g. too easy to guess).
+
+ The following method-specific message numbers are used by the
+ password authentication method.
+
+ #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60
+
+
+3.5 Host-Based Authentication: hostbased
+
+ Some sites wish to allow authentication based on the host where the
+ user is coming from, and the user name on the remote host. While
+ this form of authentication is not suitable for high-security sites,
+ it can be very convenient in many environments. This form of
+ authentication is OPTIONAL. When used, special care SHOULD be taken
+ to prevent a regular user from obtaining the private host key.
+
+ The client requests this form of authentication by sending the
+ following message. It is similar to the UNIX "rhosts" and
+ "hosts.equiv" styles of authentication, except that the identity of
+ the client host is checked more rigorously.
+
+ This method works by having the client send a signature created with
+ the private key of the client host, which the server checks with that
+ host's public key. Once the client host's identity is established,
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 11]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ authorization (but no further authentication) is performed based on
+ the user names on the server and the client, and the client host
+ name.
+
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name
+ string service
+ string "hostbased"
+ string public key algorithm for host key
+ string public host key and certificates for client host
+ string client host name (FQDN; US-ASCII)
+ string user name on the client host (ISO-10646 UTF-8)
+ string signature
+
+ Public key algorithm names for use in "public key algorithm for host
+ key" are defined in the transport layer specification. The "public
+ host key for client host" may include certificates.
+
+ Signature is a signature with the private host key of the following
+ data, in this order:
+
+ string session identifier
+ byte SSH_MSG_USERAUTH_REQUEST
+ string user name
+ string service
+ string "hostbased"
+ string public key algorithm for host key
+ string public host key and certificates for client host
+ string client host name (FQDN; US-ASCII)
+ string user name on the client host(ISO-10646 UTF-8)
+
+ The server MUST verify that the host key actually belongs to the
+ client host named in the message, that the given user on that host is
+ allowed to log in, and that the signature is a valid signature on the
+ appropriate value by the given host key. The server MAY ignore the
+ client user name, if it wants to authenticate only the client host.
+
+ It is RECOMMENDED that whenever possible, the server perform
+ additional checks to verify that the network address obtained from
+ the (untrusted) network matches the given client host name. This
+ makes exploiting compromised host keys more difficult. Note that
+ this may require special handling for connections coming through a
+ firewall.
+
+4. Security Considerations
+
+ The purpose of this protocol is to perform client user
+ authentication. It assumed that this runs over a secure transport
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 12]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ layer protocol, which has already authenticated the server machine,
+ established an encrypted communications channel, and computed a
+ unique session identifier for this session. The transport layer
+ provides forward secrecy for password authentication and other
+ methods that rely on secret data.
+
+ Full security considerations for this protocol are provided in
+ Section 8 of [SSH-ARCH]
+
+Normative
+
+ [SSH-ARCH]
+ Ylonen, T., "SSH Protocol Architecture", I-D
+ draft-ietf-architecture-15.txt, Oct 2003.
+
+ [SSH-TRANS]
+ Ylonen, T., "SSH Transport Layer Protocol", I-D
+ draft-ietf-transport-17.txt, Oct 2003.
+
+ [SSH-USERAUTH]
+ Ylonen, T., "SSH Authentication Protocol", I-D
+ draft-ietf-userauth-18.txt, Oct 2003.
+
+ [SSH-CONNECT]
+ Ylonen, T., "SSH Connection Protocol", I-D
+ draft-ietf-connect-18.txt, Oct 2003.
+
+ [SSH-NUMBERS]
+ Lehtinen, S. and D. Moffat, "SSH Protocol Assigned
+ Numbers", I-D draft-ietf-secsh-assignednumbers-05.txt, Oct
+ 2003.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+Informative
+
+ [RFC3066] Alvestrand, H., "Tags for the Identification of
+ Languages", BCP 47, RFC 3066, January 2001.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 13]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+Authors' Addresses
+
+ Tatu Ylonen
+ SSH Communications Security Corp
+ Fredrikinkatu 42
+ HELSINKI FIN-00100
+ Finland
+
+
+
+ Darren J. Moffat (editor)
+ Sun Microsystems, Inc
+ 17 Network Circle
+ Menlo Park 95025
+ USA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 14]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+ The IETF has been notified of intellectual property rights claimed in
+ regard to some or all of the specification contained in this
+ document. For more information consult the online list of claimed
+ rights.
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 15]
+
+Internet-Draft SSH Authentication Protocol September 2002
+
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen & Moffat Expires March 2, 2003 [Page 16] \ No newline at end of file
diff --git a/lib/ssh/ebin/.gitignore b/lib/ssh/ebin/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ssh/ebin/.gitignore
diff --git a/lib/ssh/examples/Makefile b/lib/ssh/examples/Makefile
new file mode 100644
index 0000000000..cd8b3c797a
--- /dev/null
+++ b/lib/ssh/examples/Makefile
@@ -0,0 +1,76 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2005-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(SSH_VSN)
+
+# ----------------------------------------------------
+# Release Macros
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+
+MODULES = \
+ ssh_sample_cli
+
+ERL_FILES= $(MODULES:=.erl)
+
+# TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+TARGET_FILES = $(MODULES:=.beam)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += -pa ../ebin -I ../src
+EBIN = .
+
+# ----------------------------------------------------
+# Make Rules
+# ----------------------------------------------------
+debug opt: $(TARGET_FILES)
+
+debug: ERLC_FLAGS += -Ddebug
+
+clean:
+ rm -f $(TARGET_FILES) *~ *.beam
+
+docs:
+
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/examples
+ $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/examples
+
+release_docs_spec:
+
diff --git a/lib/ssh/examples/ssh_sample_cli.erl b/lib/ssh/examples/ssh_sample_cli.erl
new file mode 100644
index 0000000000..2505c1b759
--- /dev/null
+++ b/lib/ssh/examples/ssh_sample_cli.erl
@@ -0,0 +1,353 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_sample_cli).
+
+%% api
+-export([listen/1, listen/2]).
+
+%% %% our shell function
+%% -export([start_our_shell/1]).
+
+%% our command functions
+-export([cli_prime/1, cli_primes/1, cli_gcd/2, cli_lcm/2,
+ cli_factors/1, cli_exit/0, cli_rho/1, cli_help/0,
+ cli_crash/0, cli_users/0, cli_self/0,
+ cli_user/0, cli_host/0]).
+
+%% imports
+-import(lists, [reverse/1, reverse/2, seq/2, prefix/2]).
+-import(math, [sqrt/1]).
+
+
+listen(Port) ->
+ listen(Port, []).
+
+listen(Port, Options) ->
+ ssh_cli:listen(fun(U, H) -> start_our_shell(U, H) end, Port, Options).
+
+%% our_routines
+our_routines() ->
+ [
+ {"crash", cli_crash, " crash the cli"},
+ {"exit", cli_exit, " exit application"},
+ {"factors", cli_factors,"<int> prime factors of <int>"},
+ {"gcd", cli_gcd, "<int> <int> greatest common divisor"},
+ {"help", cli_help, " help text"},
+ {"lcm", cli_lcm, "<int> <int> least common multiplier"},
+ {"prime", cli_prime, "<int> check for primality"},
+ {"primes", cli_primes, "<int> print all primes up to <int>"},
+ {"rho", cli_rho, "<int> prime factors using rho's alg."},
+ {"who", cli_users, " lists users"},
+ {"user", cli_user, " print name of user"},
+ {"host", cli_host, " print host addr"},
+ {"self", cli_self, " print my pid"}
+ ].
+
+%% (we could of course generate this from module_info() something like this)
+%% our_routines1() ->
+%% {value, {exports, Exports}} =
+%% lists:keysearch(exports, 1, module_info()),
+%% get_cli(Exports, []).
+
+%% our_args1(N) -> our_args1(N, "").
+%% our_args1(0, S) -> S;
+%% our_args1(N, S) -> our_args1(N-1, S ++ "<int> ").
+
+%% get_cli([], Acc) ->
+%% lists:sort(Acc);
+%% get_cli([{A, Arity} | Rest], Acc) ->
+%% L = atom_to_list(A),
+%% case lists:prefix("cli_", L) of
+%% true -> get_cli(Rest, [{tl4(L), A, our_args1(Arity)} | Acc]);
+%% false -> get_cli(Rest, Acc)
+%% end.
+
+%% the longest common prefix of two strings
+common_prefix([C | R1], [C | R2], Acc) ->
+ common_prefix(R1, R2, [C | Acc]);
+common_prefix(_, _, Acc) ->
+ reverse(Acc).
+
+%% longest prefix in a list, given a prefix
+longest_prefix(List, Prefix) ->
+ case [A || {A, _, _} <- List, prefix(Prefix, A)] of
+ [] ->
+ {none, List};
+ [S | Rest] ->
+ NewPrefix0 =
+ lists:foldl(fun(A, P) ->
+ common_prefix(A, P, [])
+ end, S, Rest),
+ NewPrefix = nthtail(length(Prefix), NewPrefix0),
+ {prefix, NewPrefix, [S | Rest]}
+ end.
+
+%%% our expand function (called when the user presses TAB)
+%%% input: a reversed list with the row to left of the cursor
+%%% output: {yes|no, Expansion, ListofPossibleMatches}
+%%% where the atom no yields a beep
+%%% Expansion is a string inserted at the cursor
+%%% List... is a list that will be printed
+%%% Here we beep on prefixes that don't match and when the command
+%%% filled in
+expand([$ | _]) ->
+ {no, "", []};
+expand(RevBefore) ->
+ Before = reverse(RevBefore),
+ case longest_prefix(our_routines(), Before) of
+ {prefix, P, [_]} ->
+ {yes, P ++ " ", []};
+ {prefix, "", M} ->
+ {yes, "", M};
+ {prefix, P, _M} ->
+ {yes, P, []};
+ {none, _M} ->
+ {no, "", []}
+ end.
+
+%%% spawns out shell loop, we use plain io to input and output
+%%% over ssh (the group module is our group leader, and takes
+%%% care of sending input to the ssh_sample_cli server)
+start_our_shell(User, Peer) ->
+ spawn(fun() ->
+ io:setopts([{expand_fun, fun(Bef) -> expand(Bef) end}]),
+ io:format("Enter command\n"),
+ put(user, User),
+ put(peer_name, Peer),
+ our_shell_loop()
+ end).
+
+%%% an ordinary Read-Eval-Print-loop
+our_shell_loop() ->
+ % Read
+ Line = io:get_line({format, "CLI> ", []}),
+ % Eval
+ Result = eval_cli(Line),
+ % Print
+ io:format("---> ~p\n", [Result]),
+ case Result of
+ done -> exit(normal);
+ crash -> 1 / 0;
+ _ -> our_shell_loop()
+ end.
+
+%%% translate a command to a function
+command_to_function(Command) ->
+ case lists:keysearch(Command, 1, our_routines()) of
+ {value, {_, Proc, _}} -> Proc;
+ false -> unknown_cli
+ end.
+
+%%% evaluate a command line
+eval_cli(Line) ->
+ case string:tokens(Line, " \n") of
+ [] -> [];
+ [Command | ArgStrings] ->
+ Proc = command_to_function(Command),
+ case fix_args(ArgStrings) of
+ {ok, Args} ->
+ case catch apply(?MODULE, Proc, Args) of
+ {'EXIT', Error} ->
+ {error, Error}; % wrong_number_of_arguments};
+ Result ->
+ Result
+ end;
+ Error ->
+ Error
+ end
+ end.
+
+%%% make command arguments to integers
+fix_args(ArgStrings) ->
+ case catch [list_to_integer(A) || A <- ArgStrings] of
+ {'EXIT', _} ->
+ {error, only_integer_arguments};
+ Args ->
+ {ok, Args}
+ end.
+
+%%% the commands, check for reasonable arguments here too
+cli_prime(N) when N < 1000000000 ->
+ rho(N) == [N] andalso is_prime(N);
+cli_prime(N) when N < 10000 ->
+ is_prime(N).
+
+cli_primes(N) when N < 1000000 ->
+ primes(N).
+
+cli_gcd(A, B) when is_integer(A), is_integer(B) ->
+ gcd(A, B).
+
+cli_lcm(A, B) when is_integer(A), is_integer(B) ->
+ lcm(A, B).
+
+cli_factors(A) when A < 1000000 ->
+ factors(A).
+
+cli_user() ->
+ get(user).
+
+cli_host() ->
+ get(peer_name).
+
+cli_users() ->
+ case ssh_userauth:get_auth_users() of
+ {ok, UsersPids} ->
+ UsersPids; % [U || {U, _} <- UsersPids];
+ E ->
+ E
+ end.
+
+cli_self() ->
+ self().
+
+cli_crash() ->
+ crash.
+
+cli_rho(A) ->
+ rho(A).
+
+cli_exit() ->
+ done.
+
+help_str(L) ->
+ help_str(L, []).
+help_str([], Acc) ->
+ lists:sort(Acc);
+help_str([{CommandName, _, HelpS} | Rest], Acc) ->
+ C = string:left(CommandName, 10),
+ help_str(Rest, [[C, " ", HelpS, $\n] | Acc]).
+
+cli_help() ->
+ HelpString = ["CLI Sample\n" | help_str(our_routines())],
+ io:format("~s\n", [HelpString]).
+
+%% a quite simple Sieve of Erastothenes (not tail-recursive, though)
+primes(Size) ->
+ era(sqrt(Size), seq(2,Size)).
+
+era(Max, [H|T]) when H =< Max ->
+ [H | era(Max, sieve([H|T], H))];
+era(_Max, L) ->
+ L.
+
+sieve([H|T], N) when H rem N =/= 0 ->
+ [H | sieve(T, N)];
+sieve([_H|T], N) ->
+ sieve(T, N);
+sieve([], _N) ->
+ [].
+
+%% another sieve, for getting the next prime incrementally
+next_prime([], _) ->
+ 2;
+next_prime([2], 2) ->
+ 3;
+next_prime(Primes, P) ->
+ next_prime1(Primes, P).
+
+next_prime1(Primes, P) ->
+ P1 = P + 2,
+ case divides(Primes, trunc(sqrt(P1)), P1) of
+ false -> P1;
+ true -> next_prime1(Primes, P1)
+ end.
+
+divides([], _, _) ->
+ false;
+divides([A | _], Nsqrt, _) when A > Nsqrt ->
+ false;
+divides([A | _], _, N) when N rem A == 0 ->
+ true;
+divides([_ | R], Nsqrt, N) ->
+ divides(R, Nsqrt, N).
+
+is_prime(P) ->
+ lists:all(fun(A) -> P rem A =/= 0 end, primes(trunc(sqrt(P)))).
+
+%% Normal gcd, Euclid
+gcd(R, Q) when abs(Q) < abs(R) -> gcd1(Q,R);
+gcd(R, Q) -> gcd1(R,Q).
+
+gcd1(0, Q) -> Q;
+gcd1(R, Q) ->
+ gcd1(Q rem R, R).
+
+%% Least common multiple of (R,Q)
+lcm(0, _Q) -> 0;
+lcm(_R, 0) -> 0;
+lcm(R, Q) ->
+ (Q div gcd(R, Q)) * R.
+
+%%% Prime factors of a number (na�ve implementation)
+factors(N) ->
+ Nsqrt = trunc(sqrt(N)),
+ factors([], N, 2, Nsqrt, []).
+
+factors(_Primes, N, Prime, Nsqrt, Factors) when Prime > Nsqrt ->
+ reverse(Factors, [N]);
+factors(Primes, N, Prime, Nsqrt, Factors) ->
+ case N rem Prime of
+ 0 ->
+ %%io:format("factor ------- ~p\n", [Prime]),
+ N1 = N div Prime,
+ factors(Primes, N1, Prime, trunc(sqrt(N1)), [Prime|Factors]);
+ _ ->
+ Primes1 = Primes ++ [Prime],
+ Prime1 = next_prime(Primes1, Prime),
+ factors(Primes1, N, Prime1, Nsqrt, Factors)
+ end.
+
+%%% Prime factors using Rho's algorithm ("reminded" from wikipedia.org)
+%%% (should perhaps have used Brent instead, but it's not as readable)
+rho_pseudo(X, C, N) ->
+ (X * X + C) rem N.
+
+rho(N) when N > 1000 ->
+ case rho(2, 2, 1, N, fun(X) -> rho_pseudo(X, 1, N) end) of
+ failure ->
+ [N];
+ F ->
+ lists:sort(rho(F) ++ rho(N div F))
+ end;
+rho(N) ->
+ factors(N).
+
+rho(X, Y, 1, N, Pseudo) ->
+ X1 = Pseudo(X),
+ Y1 = Pseudo(Pseudo(Y)),
+ D = gcd(absdiff(X1, Y1), N),
+ rho(X1, Y1, D, N, Pseudo);
+rho(_X, _Y, D, N, _Pseudo) when 1 < D, D < N ->
+ D;
+rho(_X, _Y, D, N, _Pseudo) when D == N ->
+ failure.
+
+absdiff(A, B) when A > B ->
+ A - B;
+absdiff(A, B) ->
+ B - A.
+
+%%% nthtail as in lists, but no badarg if n > the length of list
+nthtail(0, A) -> A;
+nthtail(N, [_ | A]) -> nthtail(N-1, A);
+nthtail(_, _) -> [].
diff --git a/lib/ssh/info b/lib/ssh/info
new file mode 100644
index 0000000000..41a2a2ccf0
--- /dev/null
+++ b/lib/ssh/info
@@ -0,0 +1,2 @@
+group: comm
+short: Secure Shell application with sftp and ssh support \ No newline at end of file
diff --git a/lib/ssh/priv/.gitignore b/lib/ssh/priv/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ssh/priv/.gitignore
diff --git a/lib/ssh/src/DSS.asn1 b/lib/ssh/src/DSS.asn1
new file mode 100755
index 0000000000..77aca3808b
--- /dev/null
+++ b/lib/ssh/src/DSS.asn1
@@ -0,0 +1,20 @@
+DSS DEFINITIONS EXPLICIT TAGS ::=
+
+BEGIN
+
+-- EXPORTS ALL
+-- All types and values defined in this module are exported for use
+-- in other ASN.1 modules.
+
+DSAPrivateKey ::= SEQUENCE {
+ version INTEGER,
+ p INTEGER, -- p
+ q INTEGER, -- q
+ g INTEGER, -- q
+ y INTEGER, -- y
+ x INTEGER -- x
+}
+
+END
+
+
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
new file mode 100644
index 0000000000..7abf06e52b
--- /dev/null
+++ b/lib/ssh/src/Makefile
@@ -0,0 +1,157 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(SSH_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+MODULES= \
+ ssh \
+ ssh_sup \
+ sshc_sup \
+ sshd_sup \
+ ssh_channel \
+ ssh_connection \
+ ssh_connection_handler \
+ ssh_connection_manager \
+ ssh_connection_controler \
+ ssh_shell \
+ ssh_system_sup \
+ ssh_subsystem_sup \
+ ssh_channel_sup \
+ ssh_acceptor_sup \
+ ssh_acceptor \
+ ssh_app \
+ ssh_auth\
+ ssh_bits \
+ ssh_cli \
+ ssh_cm \
+ ssh_dsa \
+ ssh_file \
+ ssh_io \
+ ssh_math \
+ ssh_no_io \
+ ssh_rsa \
+ ssh_sftp \
+ ssh_sftpd \
+ ssh_sftpd_file\
+ ssh_sftpd_file_api \
+ ssh_ssh \
+ ssh_sshd \
+ ssh_transport \
+ ssh_userreg \
+ ssh_xfer
+
+PUBLIC_HRL_FILES= ssh.hrl ssh_userauth.hrl ssh_xfer.hrl
+
+ERL_FILES= $(MODULES:%=%.erl) $(ASN_ERLS)
+
+ALL_MODULES= $(MODULES) $(ASN_MODULES)
+
+TARGET_FILES= $(ALL_MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
+
+APP_FILE= ssh.app
+APPUP_FILE= ssh.appup
+
+APP_SRC= $(APP_FILE).src
+APP_TARGET= $(EBIN)/$(APP_FILE)
+
+APPUP_SRC= $(APPUP_FILE).src
+APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+ASN_MODULES = PKCS-1 DSS
+ASN_ASNS = $(ASN_MODULES:%=%.asn1)
+ASN_ERLS = $(ASN_MODULES:%=%.erl)
+ASN_HRLS = $(ASN_MODULES:%=%.hrl)
+ASN_DBS = $(ASN_MODULES:%=%.asn1db)
+ASN_TABLES = $(ASN_MODULES:%=%.table)
+
+ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +inline
+
+INTERNAL_HRL_FILES = $(ASN_HRLS) ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += -pa$(EBIN)
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt: $(TARGET_FILES)
+
+debug: ERLC_FLAGS += -Ddebug
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+ rm -f $(ASN_ERLS) $(ASN_HRLS) $(ASN_DBS)
+
+$(TARGET_FILES): ssh.hrl
+
+# $(EBIN)/ssh_sftpd_file.$(EMULATOR): ERLC_FLAGS += -pa$(EBIN)
+# $(EBIN)/ssh_sftpd_file.$(EMULATOR): $(EBIN)/ssh_sftpd_file_api.$(EMULATOR)
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+%.hrl: %.asn1
+ erlc $(ASN_FLAGS) $<
+
+DSS.hrl DSS.erl: DSS.asn1
+PKCS-1.hrl PKCS-1.erl: PKCS-1.asn1
+
+$(EBIN)/ssh_file.$(EMULATOR): $(ASN_HRLS)
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/include
+ $(INSTALL_DATA) $(PUBLIC_HRL_FILES) $(RELSYSDIR)/include
+
+release_docs_spec:
+
diff --git a/lib/ssh/src/PKCS-1.asn1 b/lib/ssh/src/PKCS-1.asn1
new file mode 100755
index 0000000000..e7d6b18c63
--- /dev/null
+++ b/lib/ssh/src/PKCS-1.asn1
@@ -0,0 +1,116 @@
+PKCS-1 {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)
+ modules(0) pkcs-1(1)
+}
+
+-- $Revision: 1.1 $
+
+DEFINITIONS EXPLICIT TAGS ::=
+
+BEGIN
+
+-- IMPORTS id-sha256, id-sha384, id-sha512
+-- FROM NIST-SHA2 {
+-- joint-iso-itu-t(2) country(16) us(840) organization(1)
+-- gov(101) csor(3) nistalgorithm(4) modules(0) sha2(1)
+-- };
+
+pkcs-1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1
+}
+
+rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
+
+id-RSAES-OAEP OBJECT IDENTIFIER ::= { pkcs-1 7 }
+
+id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 }
+
+id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
+
+md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
+md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
+sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
+sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
+sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
+sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
+
+id-sha1 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) oiw(14) secsig(3)
+ algorithms(2) 26
+}
+
+id-md2 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
+}
+
+id-md5 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
+}
+
+id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 }
+
+
+RSAPublicKey ::= SEQUENCE {
+ modulus INTEGER, -- n
+ publicExponent INTEGER -- e
+}
+
+RSAPrivateKey ::= SEQUENCE {
+ version Version,
+ modulus INTEGER, -- n
+ publicExponent INTEGER, -- e
+ privateExponent INTEGER, -- d
+ prime1 INTEGER, -- p
+ prime2 INTEGER, -- q
+ exponent1 INTEGER, -- d mod (p-1)
+ exponent2 INTEGER, -- d mod (q-1)
+ coefficient INTEGER, -- (inverse of q) mod p
+ otherPrimeInfos OtherPrimeInfos OPTIONAL
+}
+
+Version ::= INTEGER { two-prime(0), multi(1) }
+ (CONSTRAINED BY {
+ -- version must be multi if otherPrimeInfos present --
+ })
+
+OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
+
+OtherPrimeInfo ::= SEQUENCE {
+ prime INTEGER, -- ri
+ exponent INTEGER, -- di
+ coefficient INTEGER -- ti
+}
+
+Algorithm ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL
+}
+
+AlgorithmNull ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters NULL
+}
+
+
+RSASSA-PSS-params ::= SEQUENCE {
+ hashAlgorithm [0] Algorithm, -- DEFAULT sha1,
+ maskGenAlgorithm [1] Algorithm, -- DEFAULT mgf1SHA1,
+ saltLength [2] INTEGER DEFAULT 20,
+ trailerField [3] TrailerField DEFAULT trailerFieldBC
+}
+
+TrailerField ::= INTEGER { trailerFieldBC(1) }
+
+DigestInfo ::= SEQUENCE {
+ digestAlgorithm Algorithm,
+ digest OCTET STRING
+}
+
+DigestInfoNull ::= SEQUENCE {
+ digestAlgorithm AlgorithmNull,
+ digest OCTET STRING
+}
+
+
+END -- PKCS1Definitions
+
diff --git a/lib/ssh/src/prebuild.skip b/lib/ssh/src/prebuild.skip
new file mode 100644
index 0000000000..1d7552d98d
--- /dev/null
+++ b/lib/ssh/src/prebuild.skip
@@ -0,0 +1,2 @@
+DSS.asn1db
+PKCS-1.asn1db
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
new file mode 100644
index 0000000000..9319f39591
--- /dev/null
+++ b/lib/ssh/src/ssh.app.src
@@ -0,0 +1,48 @@
+%%% This is an -*- erlang -*- file.
+
+{application, ssh,
+ [{description, "SSH-2 for Erlang/OTP"},
+ {vsn, "%VSN%"},
+ {modules, ['DSS',
+ 'PKCS-1',
+ ssh,
+ ssh_app,
+ ssh_acceptor,
+ ssh_acceptor_sup,
+ ssh_auth,
+ ssh_bits,
+ ssh_cli,
+ ssh_channel,
+ ssh_channel_sup,
+ ssh_cm,
+ ssh_connection,
+ ssh_connection_handler,
+ ssh_connection_manager,
+ ssh_connection_controler,
+ ssh_shell,
+ sshc_sup,
+ sshd_sup,
+ ssh_dsa,
+ ssh_file,
+ ssh_io,
+ ssh_math,
+ ssh_no_io,
+ ssh_rsa,
+ ssh_sftp,
+ ssh_sftpd,
+ ssh_sftpd_file,
+ ssh_sftpd_file_api,
+ ssh_ssh,
+ ssh_sshd,
+ ssh_subsystem_sup,
+ ssh_sup,
+ ssh_system_sup,
+ ssh_transport,
+ ssh_userreg,
+ ssh_xfer]},
+ {registered, []},
+ {applications, [kernel, stdlib, crypto]},
+ {env, []},
+ {mod, {ssh_app, []}}]}.
+
+
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
new file mode 100644
index 0000000000..3bf772b42b
--- /dev/null
+++ b/lib/ssh/src/ssh.appup.src
@@ -0,0 +1,37 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+{"%VSN%",
+ [
+ {"1.1.6", [{restart_application, ssh}]},
+ {"1.1.5", [{restart_application, ssh}]},
+ {"1.1.4", [{restart_application, ssh}]},
+ {"1.1.3", [{restart_application, ssh}]},
+ {"1.1.2", [{restart_application, ssh}]}
+ ],
+ [
+ {"1.1.6", [{restart_application, ssh}]},
+ {"1.1.5", [{restart_application, ssh}]},
+ {"1.1.4", [{restart_application, ssh}]},
+ {"1.1.3", [{restart_application, ssh}]},
+ {"1.1.2", [{restart_application, ssh}]}
+ ]
+}.
+
+
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
new file mode 100644
index 0000000000..f9a986a8b6
--- /dev/null
+++ b/lib/ssh/src/ssh.erl
@@ -0,0 +1,339 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+
+-export([start/0, start/1, stop/0, connect/3, close/1, connection_info/2,
+ channel_info/3,
+ daemon/1, daemon/2, daemon/3,
+ stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2,
+ shell/1, shell/2, shell/3]).
+
+%%--------------------------------------------------------------------
+%% Function: start([, Type]) -> ok
+%%
+%% Type = permanent | transient | temporary
+%%
+%% Description: Starts the inets application. Default type
+%% is temporary. see application(3)
+%%--------------------------------------------------------------------
+start() ->
+ application:start(ssh).
+
+start(Type) ->
+ application:start(ssh, Type).
+
+%%--------------------------------------------------------------------
+%% Function: stop() -> ok
+%%
+%% Description: Stops the inets application.
+%%--------------------------------------------------------------------
+stop() ->
+ application:stop(ssh).
+
+%%--------------------------------------------------------------------
+%% Function: connect(Host, Port, Options) ->
+%% connect(Host, Port, Options, Timeout -> ConnectionRef | {error, Reason}
+%%
+%% Host - string()
+%% Port - integer()
+%% Options - [{Option, Value}]
+%% Timeout - infinity | integer().
+%%
+%% Description: Starts an ssh connection.
+%%--------------------------------------------------------------------
+connect(Host, Port, Options) ->
+ connect(Host, Port, Options, infinity).
+connect(Host, Port, Options, Timeout) ->
+ {SocketOpts, Opts} = handle_options(Options),
+ DisableIpv6 = proplists:get_value(ip_v6_disabled, Opts, false),
+ Inet = inetopt(DisableIpv6),
+ try sshc_sup:start_child([[{address, Host}, {port, Port},
+ {role, client},
+ {channel_pid, self()},
+ {socket_opts, [Inet | SocketOpts]},
+ {ssh_opts, [{host, Host}| Opts]}]]) of
+ {ok, ConnectionSup} ->
+ {ok, Manager} =
+ ssh_connection_controler:connection_manager(ConnectionSup),
+ MRef = erlang:monitor(process, Manager),
+ receive
+ {Manager, is_connected} ->
+ do_demonitor(MRef, Manager),
+ {ok, Manager};
+ %% When the connection fails
+ %% ssh_connection_sup:connection_manager
+ %% might return undefined as the connection manager
+ %% could allready have terminated, so we will not
+ %% match the Manager in this case
+ {_, not_connected, {error, Reason}} ->
+ do_demonitor(MRef, Manager),
+ {error, Reason};
+ {_, not_connected, Other} ->
+ do_demonitor(MRef, Manager),
+ {error, Other};
+ {'DOWN', MRef, _, Manager, Reason} when is_pid(Manager) ->
+ receive %% Clear EXIT message from queue
+ {'EXIT', Manager, _What} ->
+ {error, Reason}
+ after 0 ->
+ {error, Reason}
+ end
+ after Timeout ->
+ do_demonitor(MRef, Manager),
+ ssh_connection_manager:stop(Manager),
+ {error, timeout}
+ end
+ catch
+ exit:{noproc, _} ->
+ {error, ssh_not_started}
+ end.
+
+do_demonitor(MRef, Manager) ->
+ erlang:demonitor(MRef),
+ receive
+ {'DOWN', MRef, _, Manager, _} ->
+ ok
+ after 0 ->
+ ok
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Function: close(ConnectionRef) -> ok
+%%
+%% Description: Closes an ssh connection.
+%%--------------------------------------------------------------------
+close(ConnectionRef) ->
+ ssh_connection_manager:stop(ConnectionRef).
+
+%%--------------------------------------------------------------------
+%% Function: connection_info(ConnectionRef) -> [{Option, Value}]
+%%
+%% Description: Retrieves information about a connection.
+%%--------------------------------------------------------------------
+connection_info(ConnectionRef, Options) ->
+ ssh_connection_manager:connection_info(ConnectionRef, Options).
+
+%%--------------------------------------------------------------------
+%% Function: channel_info(ConnectionRef) -> [{Option, Value}]
+%%
+%% Description: Retrieves information about a connection.
+%%--------------------------------------------------------------------
+channel_info(ConnectionRef, ChannelId, Options) ->
+ ssh_connection_manager:channel_info(ConnectionRef, ChannelId, Options).
+
+%%--------------------------------------------------------------------
+%% Function: daemon(Port) ->
+%% daemon(Port, Options) ->
+%% daemon(Address, Port, Options) -> SshSystemRef
+%%
+%% Description: Starts a server listening for SSH connections
+%% on the given port.
+%%--------------------------------------------------------------------
+daemon(Port) ->
+ daemon(Port, []).
+
+daemon(Port, Options) ->
+ daemon(any, Port, Options).
+
+daemon(HostAddr, Port, Options0) ->
+ Options1 = case proplists:get_value(shell, Options0) of
+ undefined ->
+ [{shell, {shell, start, []}} | Options0];
+ _ ->
+ Options0
+ end,
+ DisableIpv6 = proplists:get_value(ip_v6_disabled, Options0, false),
+ {Host, Inet, Options} = case HostAddr of
+ any ->
+ {ok, Host0} = inet:gethostname(),
+ {Host0, inetopt(DisableIpv6), Options1};
+ {_,_,_,_} ->
+ {HostAddr, inet,
+ [{ip, HostAddr} | Options1]};
+ {_,_,_,_,_,_,_,_} ->
+ {HostAddr, inet6,
+ [{ip, HostAddr} | Options1]}
+ end,
+ start_daemon(Host, Port, [{role, server} | Options], Inet).
+
+%%--------------------------------------------------------------------
+%% Function: stop_listener(SysRef) -> ok
+%% stop_listener(Address, Port) -> ok
+%%
+%%
+%% Description: Stops the listener, but leaves
+%% existing connections started by the listener up and running.
+%%--------------------------------------------------------------------
+stop_listener(SysSup) ->
+ ssh_system_sup:stop_listener(SysSup).
+stop_listener(Address, Port) ->
+ ssh_system_sup:stop_listener(Address, Port).
+
+%%--------------------------------------------------------------------
+%% Function: stop_daemon(SysRef) -> ok
+%%% stop_daemon(Address, Port) -> ok
+%%
+%%
+%% Description: Stops the listener and all connections started by
+%% the listener.
+%%--------------------------------------------------------------------
+stop_daemon(SysSup) ->
+ ssh_system_sup:stop_system(SysSup).
+stop_daemon(Address, Port) ->
+ ssh_system_sup:stop_system(Address, Port).
+
+%%--------------------------------------------------------------------
+%% Function: shell(Host [,Port,Options]) -> {ok, ConnectionRef} |
+%% {error, Reason}
+%%
+%% Host = string()
+%% Port = integer()
+%% Options = [{Option, Value}]
+%%
+%% Description: Starts an interactive shell to an SSH server on the
+%% given <Host>. The function waits for user input,
+%% and will not return until the remote shell is ended.(e.g. on
+%% exit from the shell)
+%%--------------------------------------------------------------------
+shell(Host) ->
+ shell(Host, ?SSH_DEFAULT_PORT, []).
+shell(Host, Options) ->
+ shell(Host, ?SSH_DEFAULT_PORT, Options).
+shell(Host, Port, Options) ->
+ case connect(Host, Port, Options) of
+ {ok, ConnectionRef} ->
+ case ssh_connection:session_channel(ConnectionRef, infinity) of
+ {ok,ChannelId} ->
+ Args = [{channel_cb, ssh_shell},
+ {init_args,[ConnectionRef, ChannelId]},
+ {cm, ConnectionRef}, {channel_id, ChannelId}],
+ {ok, State} = ssh_channel:init([Args]),
+ ssh_channel:enter_loop(State);
+ Error ->
+ Error
+ end;
+ Error ->
+ Error
+ end.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+start_daemon(Host, Port, Options, Inet) ->
+ {SocketOpts, Opts} = handle_options(Options),
+ case ssh_system_sup:system_supervisor(Host, Port) of
+ undefined ->
+ %% TODO: It would proably make more sense to call the
+ %% address option host but that is a too big change at the
+ %% monent. The name is a legacy name!
+ try sshd_sup:start_child([{address, Host},
+ {port, Port}, {role, server},
+ {socket_opts, [Inet | SocketOpts]},
+ {ssh_opts, Opts}]) of
+ {ok, SysSup} ->
+ {ok, SysSup};
+ {error, {already_started, _}} ->
+ {error, eaddrinuse}
+ catch
+ exit:{noproc, _} ->
+ {error, ssh_not_started}
+ end;
+ Sup ->
+ case ssh_system_sup:restart_acceptor(Host, Port) of
+ {ok, _} ->
+ {ok, Sup};
+ _ ->
+ {error, eaddrinuse}
+ end
+ end.
+
+handle_options(Opts) ->
+ handle_options(proplists:unfold(Opts), [], []).
+handle_options([], SockOpts, Opts) ->
+ {SockOpts, Opts};
+%% TODO: Could do some type checks here on plain ssh-opts
+handle_options([{system_dir, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{user_dir, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{user_dir_fun, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{silently_accept_hosts, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{user_interaction, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{public_key_alg, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{connect_timeout, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{user, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{password, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{user_passwords, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{pwdfun, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{user_auth, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{key_cb, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{role, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{channel, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{compression, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{allow_user_interaction, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{infofun, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{connectfun, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{disconnectfun , _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{failfun, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{ip_v6_disabled, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{ip, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, [Opt |SockOpts], Opts);
+handle_options([{ifaddr, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, [Opt |SockOpts], Opts);
+handle_options([{fd, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, [Opt | SockOpts], Opts);
+handle_options([{nodelay, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, [Opt | SockOpts], Opts);
+handle_options([Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]).
+
+inetopt(true) ->
+ inet6;
+
+inetopt(false) ->
+ inet.
+
+
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
new file mode 100644
index 0000000000..0e4285295c
--- /dev/null
+++ b/lib/ssh/src/ssh.hrl
@@ -0,0 +1,180 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%
+%% SSH definitions
+%%
+
+-ifndef(SSH_HRL).
+-define(SSH_HRL, 1).
+
+-define(SSH_DEFAULT_PORT, 22).
+-define(SSH_MAX_PACKET_SIZE, (256*1024)).
+-define(SSH_LENGHT_INDICATOR_SIZE, 4).
+
+-define(FALSE, 0).
+-define(TRUE, 1).
+%% basic binary constructors
+-define(BOOLEAN(X), X:8/unsigned-big-integer).
+-define(BYTE(X), X:8/unsigned-big-integer).
+-define(UINT16(X), X:16/unsigned-big-integer).
+-define(UINT32(X), X:32/unsigned-big-integer).
+-define(UINT64(X), X:64/unsigned-big-integer).
+-define(STRING(X), ?UINT32((size(X))), (X)/binary).
+
+%% building macros
+-define(boolean(X),
+ case X of
+ true -> <<?BOOLEAN(1)>>;
+ false -> (<<?BOOLEAN(0)>>)
+ end).
+
+-define(byte(X), << ?BYTE(X) >> ).
+-define(uint16(X), << ?UINT16(X) >> ).
+-define(uint32(X), << ?UINT32(X) >> ).
+-define(uint64(X), << ?UINT64(X) >> ).
+-define(string(X), << ?STRING(list_to_binary(X)) >> ).
+-define(binary(X), << ?STRING(X) >>).
+
+-ifdef(debug).
+-define(dbg(Debug, Fmt, As),
+ case (Debug) of
+ true ->
+ io:format([$# | (Fmt)], (As));
+ _ ->
+ ok
+ end).
+-else.
+-define(dbg(Debug, Fmt, As), ok).
+-endif.
+
+-define(SSH_CIPHER_NONE, 0).
+-define(SSH_CIPHER_3DES, 3).
+-define(SSH_CIPHER_AUTHFILE, ?SSH_CIPHER_3DES).
+
+-record(ssh,
+ {
+ %%state, %% what it's waiting for
+
+ role, %% client | server
+ peer, %% string version of peer address
+
+ c_vsn, %% client version {Major,Minor}
+ s_vsn, %% server version {Major,Minor}
+
+ c_version, %% client version string
+ s_version, %% server version string
+
+ c_keyinit, %% binary payload of kexinit packet
+ s_keyinit, %% binary payload of kexinit packet
+
+ algorithms, %% #alg{}
+
+ kex, %% key exchange algorithm
+ hkey, %% host key algorithm
+ key_cb, %% Private/Public key callback module
+ io_cb, %% Interaction callback module
+
+ send_mac = none, %% send MAC algorithm
+ send_mac_key, %% key used in send MAC algorithm
+ send_mac_size = 0,
+
+ recv_mac = none, %% recv MAC algorithm
+ recv_mac_key, %% key used in recv MAC algorithm
+ recv_mac_size = 0,
+
+ encrypt = none, %% encrypt algorithm
+ encrypt_keys, %% encrypt keys
+ encrypt_block_size = 8,
+ encrypt_ctx,
+
+ decrypt = none, %% decrypt algorithm
+ decrypt_keys, %% decrypt keys
+ decrypt_block_size = 8,
+ decrypt_ctx, %% Decryption context
+
+ compress = none,
+ compress_ctx,
+ decompress = none,
+ decompress_ctx,
+
+ c_lng=none, %% client to server languages
+ s_lng=none, %% server to client languages
+
+ user_ack = true, %% client
+ timeout = infinity,
+
+ shared_secret, %% K from key exchange
+ exchanged_hash, %% H from key exchange
+ session_id, %% same as FIRST exchanged_hash
+
+ opts = [],
+ send_sequence = 0,
+ recv_sequence = 0,
+ keyex_key,
+ keyex_info,
+
+ %% User auth
+ user,
+ service,
+ userauth_quiet_mode, % boolean()
+ userauth_supported_methods , %
+ userauth_methods,
+ userauth_preference
+ }).
+
+-record(alg,
+ {
+ kex,
+ hkey,
+ send_mac,
+ recv_mac,
+ encrypt,
+ decrypt,
+ compress,
+ decompress,
+ c_lng,
+ s_lng
+ }).
+
+-record(ssh_key,
+ {
+ type,
+ public,
+ private,
+ comment = ""
+ }).
+
+-record(ssh_pty, {term = "", % e.g. "xterm"
+ width = 80,
+ height = 25,
+ pixel_width = 1024,
+ pixel_height = 768,
+ modes = <<>>}).
+
+%% assertion macro
+-define(ssh_assert(Expr, Reason),
+ case Expr of
+ true -> ok;
+ _ -> exit(Reason)
+ end).
+
+-endif. % SSH_HRL defined
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
new file mode 100644
index 0000000000..d19fee14e1
--- /dev/null
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -0,0 +1,115 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_acceptor).
+
+%% Internal application API
+-export([start_link/5]).
+
+%% spawn export
+%% TODO: system messages
+-export([acceptor_init/6, acceptor_loop/6]).
+
+-define(SLEEP_TIME, 200).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+start_link(Port, Address, SockOpts, Opts, AcceptTimeout) ->
+ Args = [self(), Port, Address, SockOpts, Opts, AcceptTimeout],
+ proc_lib:start_link(?MODULE, acceptor_init, Args).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+acceptor_init(Parent, Port, Address, SockOpts, Opts, AcceptTimeout) ->
+ {_, Callback, _} =
+ proplists:get_value(transport, Opts, {tcp, gen_tcp, tcp_closed}),
+ case (catch do_socket_listen(Callback, Port, SockOpts)) of
+ {ok, ListenSocket} ->
+ proc_lib:init_ack(Parent, {ok, self()}),
+ acceptor_loop(Callback,
+ Port, Address, Opts, ListenSocket, AcceptTimeout);
+ Error ->
+ proc_lib:init_ack(Parent, Error),
+ error
+ end.
+
+do_socket_listen(Callback, Port, Opts) ->
+ case Callback:listen(Port, Opts) of
+ {error, eafnosupport} ->
+ Callback:listen(Port, lists:delete(inet6, Opts));
+ Other ->
+ Other
+ end.
+
+acceptor_loop(Callback, Port, Address, Opts, ListenSocket, AcceptTimeout) ->
+ case (catch Callback:accept(ListenSocket, AcceptTimeout)) of
+ {ok, Socket} ->
+ handle_connection(Callback, Address, Port, Opts, Socket),
+ ?MODULE:acceptor_loop(Callback, Port, Address, Opts,
+ ListenSocket, AcceptTimeout);
+ {error, Reason} ->
+ handle_error(Reason),
+ ?MODULE:acceptor_loop(Callback, Port, Address, Opts,
+ ListenSocket, AcceptTimeout);
+ {'EXIT', Reason} ->
+ handle_error(Reason),
+ ?MODULE:acceptor_loop(Callback, Port, Address, Opts,
+ ListenSocket, AcceptTimeout)
+ end.
+
+handle_connection(Callback, Address, Port, Options, Socket) ->
+ SystemSup = ssh_system_sup:system_supervisor(Address, Port),
+ ssh_system_sup:start_subsystem(SystemSup, Options),
+ ConnectionSup = ssh_system_sup:connection_supervisor(SystemSup),
+ {ok, Pid} =
+ ssh_connection_controler:start_manager_child(ConnectionSup,
+ [server, Socket, Options]),
+ Callback:controlling_process(Socket, Pid),
+ SshOpts = proplists:get_value(ssh_opts, Options),
+ Pid ! {start_connection, server, [Address, Port, Socket, SshOpts]}.
+
+handle_error(timeout) ->
+ ok;
+
+handle_error(enfile) ->
+ %% Out of sockets...
+ timer:sleep(?SLEEP_TIME);
+
+handle_error(emfile) ->
+ %% Too many open files -> Out of sockets...
+ timer:sleep(?SLEEP_TIME);
+
+handle_error(closed) ->
+ error_logger:info_report("The ssh accept socket was closed by "
+ "a third party. "
+ "This will not have an impact on ssh "
+ "that will open a new accept socket and "
+ "go on as nothing happened. It does however "
+ "indicate that some other software is behaving "
+ "badly."),
+ exit(normal);
+
+handle_error(Reason) ->
+ String = lists:flatten(io_lib:format("Accept error: ~p", [Reason])),
+ error_logger:error_report(String),
+ exit({accept_failed, String}).
diff --git a/lib/ssh/src/ssh_acceptor_sup.erl b/lib/ssh/src/ssh_acceptor_sup.erl
new file mode 100644
index 0000000000..707e3d3a5e
--- /dev/null
+++ b/lib/ssh/src/ssh_acceptor_sup.erl
@@ -0,0 +1,95 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The acceptor supervisor for ssh servers hangs under
+%% ssh_system_sup.
+%%----------------------------------------------------------------------
+
+-module(ssh_acceptor_sup).
+-behaviour(supervisor).
+
+-export([start_link/1, start_child/2, stop_child/2]).
+
+%% Supervisor callback
+-export([init/1]).
+
+-define(DEFAULT_TIMEOUT, 50000).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(Servers) ->
+ supervisor:start_link(?MODULE, [Servers]).
+
+start_child(AccSup, ServerOpts) ->
+ Spec = child_spec(ServerOpts),
+ case supervisor:start_child(AccSup, Spec) of
+ {error, already_present} ->
+ Address = proplists:get_value(address, ServerOpts),
+ Port = proplists:get_value(port, ServerOpts),
+ Name = id(Address, Port),
+ supervisor:delete_child(?MODULE, Name),
+ supervisor:start_child(AccSup, Spec);
+ Reply ->
+ Reply
+ end.
+
+stop_child(Address, Port) ->
+ Name = id(Address, Port),
+ case supervisor:terminate_child(?MODULE, Name) of
+ ok ->
+ supervisor:delete_child(?MODULE, Name);
+ Error ->
+ Error
+ end.
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([ServerOpts]) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = [child_spec(ServerOpts)],
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+child_spec(ServerOpts) ->
+ Address = proplists:get_value(address, ServerOpts),
+ Port = proplists:get_value(port, ServerOpts),
+ Timeout = proplists:get_value(timeout, ServerOpts, ?DEFAULT_TIMEOUT),
+ Name = id(Address, Port),
+ SocketOpts = proplists:get_value(socket_opts, ServerOpts),
+ StartFunc = {ssh_acceptor, start_link, [Port, Address,
+ [{active, false},
+ {reuseaddr, true}] ++ SocketOpts,
+ ServerOpts, Timeout]},
+ Restart = permanent,
+ Shutdown = 3600,
+ Modules = [ssh_acceptor],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+id(Address, Port) ->
+ {ssh_acceptor_sup, Address, Port}.
+
diff --git a/lib/ssh/src/ssh_app.erl b/lib/ssh/src/ssh_app.erl
new file mode 100644
index 0000000000..5793d3a321
--- /dev/null
+++ b/lib/ssh/src/ssh_app.erl
@@ -0,0 +1,34 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%% Purpose : Application master for SSH.
+
+-module(ssh_app).
+
+-behaviour(application).
+
+-export([start/2, stop/1]).
+
+start(_Type, _State) ->
+ supervisor:start_link({local, ssh_sup}, ssh_sup, []).
+
+stop(_State) ->
+ ok.
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
new file mode 100644
index 0000000000..aa74528544
--- /dev/null
+++ b/lib/ssh/src/ssh_auth.erl
@@ -0,0 +1,423 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_auth).
+
+-include("ssh.hrl").
+
+-include("ssh_auth.hrl").
+-include("ssh_transport.hrl").
+
+-export([publickey_msg/1, password_msg/1, keyboard_interactive_msg/1,
+ service_request_msg/1, init_userauth_request_msg/1,
+ userauth_request_msg/1, handle_userauth_request/3,
+ handle_userauth_info_request/3, handle_userauth_info_response/2,
+ userauth_messages/0
+ ]).
+
+%%--------------------------------------------------------------------
+%%% Internal application API
+%%--------------------------------------------------------------------
+publickey_msg([Cb, #ssh{user = User,
+ session_id = SessionId,
+ service = Service,
+ opts = Opts} = Ssh]) ->
+ ssh_bits:install_messages(userauth_pk_messages()),
+ Alg = Cb:alg_name(),
+ case ssh_file:private_identity_key(Alg, Opts) of
+ {ok, PrivKey} ->
+ PubKeyBlob = ssh_file:encode_public_key(PrivKey),
+ SigData = build_sig_data(SessionId,
+ User, Service, Alg, PubKeyBlob),
+ Sig = Cb:sign(PrivKey, SigData),
+ SigBlob = list_to_binary([?string(Alg), ?binary(Sig)]),
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_request{user = User,
+ service = Service,
+ method = "publickey",
+ data = [?TRUE,
+ ?string(Alg),
+ ?binary(PubKeyBlob),
+ ?binary(SigBlob)]},
+ Ssh);
+ _Error ->
+ not_ok
+ end.
+
+password_msg([#ssh{opts = Opts, io_cb = IoCb,
+ user = User, service = Service} = Ssh]) ->
+ ssh_bits:install_messages(userauth_passwd_messages()),
+ Password = case proplists:get_value(password, Opts) of
+ undefined ->
+ IoCb:read_password("ssh password: ");
+ PW ->
+ PW
+ end,
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_request{user = User,
+ service = Service,
+ method = "password",
+ data =
+ <<?BOOLEAN(?FALSE),
+ ?STRING(list_to_binary(Password))>>},
+ Ssh).
+
+%% See RFC 4256 for info on keyboard-interactive
+keyboard_interactive_msg([#ssh{user = User,
+ service = Service} = Ssh]) ->
+ ssh_bits:install_messages(userauth_keyboard_interactive_messages()),
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_request{user = User,
+ service = Service,
+ method = "keyboard-interactive",
+ data = << ?STRING(<<"">>),
+ ?STRING(<<>>) >> },
+ Ssh).
+
+service_request_msg(Ssh) ->
+ ssh_transport:ssh_packet(#ssh_msg_service_request{name = "ssh-userauth"},
+ Ssh#ssh{service = "ssh-userauth"}).
+
+init_userauth_request_msg(#ssh{opts = Opts} = Ssh) ->
+ case user_name(Opts) of
+ {ok, User} ->
+ Msg = #ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
+ method = "none",
+ data = <<>>},
+ CbFirst = proplists:get_value(public_key_alg, Opts,
+ ?PREFERRED_PK_ALG),
+ CbSecond = other_cb(CbFirst),
+ AllowUserInt = proplists:get_value(allow_user_interaction, Opts,
+ true),
+ Prefs = method_preference(CbFirst, CbSecond, AllowUserInt),
+ ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User,
+ userauth_preference = Prefs,
+ userauth_methods = none,
+ service = "ssh-connection"});
+ {error, no_user} ->
+ ErrStr = "Could not determine the users name",
+ throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_ILLEGAL_USER_NAME,
+ description = ErrStr,
+ language = "en"})
+ end.
+
+userauth_request_msg(#ssh{userauth_preference = []} = Ssh) ->
+ Msg = #ssh_msg_disconnect{code =
+ ?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
+ description = "Unable to connect using the available"
+ " authentication methods",
+ language = "en"},
+ {disconnect, Msg, ssh_transport:ssh_packet(Msg, Ssh)};
+
+userauth_request_msg(#ssh{userauth_methods = Methods,
+ userauth_preference = [{Pref, Module,
+ Function, Args} | Prefs]}
+ = Ssh0) ->
+ Ssh = Ssh0#ssh{userauth_preference = Prefs},
+ case lists:member(Pref, Methods) of
+ true ->
+ case Module:Function(Args ++ [Ssh]) of
+ not_ok ->
+ userauth_request_msg(Ssh);
+ Result ->
+ Result
+ end;
+ false ->
+ userauth_request_msg(Ssh)
+ end.
+
+
+handle_userauth_request(#ssh_msg_service_request{name =
+ Name = "ssh-userauth"},
+ _, Ssh) ->
+ {ok, ssh_transport:ssh_packet(#ssh_msg_service_accept{name = Name},
+ Ssh#ssh{service = "ssh-connection"})};
+
+handle_userauth_request(#ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
+ method = "password",
+ data = Data}, _,
+ #ssh{opts = Opts} = Ssh) ->
+ <<_:8, ?UINT32(Sz), BinPwd:Sz/binary>> = Data,
+ Password = binary_to_list(BinPwd),
+
+ case check_password(User, Password, Opts) of
+ true ->
+ {authorized, User,
+ ssh_transport:ssh_packet(#ssh_msg_userauth_success{}, Ssh)};
+ false ->
+ {not_authorized, {User, {passwd, Password}},
+ ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
+ authentications = "",
+ partial_success = false}, Ssh)}
+ end;
+
+handle_userauth_request(#ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
+ method = "none"}, _,
+ #ssh{userauth_supported_methods = Methods} = Ssh) ->
+ {not_authorized, {User, undefined},
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_failure{authentications = Methods,
+ partial_success = false}, Ssh)};
+
+handle_userauth_request(#ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
+ method = "publickey",
+ data = Data},
+ SessionId, #ssh{opts = Opts} = Ssh) ->
+ <<?BYTE(HaveSig), ?UINT32(ALen), BAlg:ALen/binary,
+ ?UINT32(KLen), KeyBlob:KLen/binary, SigWLen/binary>> = Data,
+ Alg = binary_to_list(BAlg),
+ case HaveSig of
+ ?TRUE ->
+ case verify_sig(SessionId, User, "ssh-connection", Alg,
+ KeyBlob, SigWLen, Opts) of
+ ok ->
+ {authorized, User,
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_success{}, Ssh)};
+ {error, Reason} ->
+ {not_authorized, {User, {error, Reason}},
+ ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
+ authentications="publickey,password",
+ partial_success = false}, Ssh)}
+ end;
+ ?FALSE ->
+ ssh_bits:install_messages(userauth_pk_messages()),
+ {not_authorized, {User, undefined},
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_pk_ok{algorithm_name = Alg,
+ key_blob = KeyBlob}, Ssh)}
+ end;
+
+handle_userauth_request(#ssh_msg_userauth_request{user = User,
+ service = "ssh-connection",
+ method = Other}, _,
+ #ssh{userauth_supported_methods = Methods} = Ssh) ->
+ {not_authorized, {User, {authmethod, Other}},
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_failure{authentications = Methods,
+ partial_success = false}, Ssh)}.
+
+handle_userauth_info_request(
+ #ssh_msg_userauth_info_request{name = Name,
+ instruction = Instr,
+ num_prompts = NumPrompts,
+ data = Data}, IoCb,
+ #ssh{opts = Opts} = Ssh) ->
+ PromptInfos = decode_keyboard_interactive_prompts(NumPrompts,Data),
+ Resps = keyboard_interact_get_responses(IoCb, Opts,
+ Name, Instr, PromptInfos),
+ %%?dbg(true, "keyboard_interactive_reply: resps=~n#~p ~n", [Resps]),
+ RespBin = list_to_binary(
+ lists:map(fun(S) -> <<?STRING(list_to_binary(S))>> end,
+ Resps)),
+ {ok,
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_info_response{num_responses = NumPrompts,
+ data = RespBin}, Ssh)}.
+
+handle_userauth_info_response(#ssh_msg_userauth_info_response{},
+ _Auth) ->
+ throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ description = "Server does not support"
+ "keyboard-interactive",
+ language = "en"}).
+userauth_messages() ->
+ [ {ssh_msg_userauth_request, ?SSH_MSG_USERAUTH_REQUEST,
+ [string,
+ string,
+ string,
+ '...']},
+
+ {ssh_msg_userauth_failure, ?SSH_MSG_USERAUTH_FAILURE,
+ [string,
+ boolean]},
+
+ {ssh_msg_userauth_success, ?SSH_MSG_USERAUTH_SUCCESS,
+ []},
+
+ {ssh_msg_userauth_banner, ?SSH_MSG_USERAUTH_BANNER,
+ [string,
+ string]}].
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+method_preference(Callback1, Callback2, true) ->
+ [{"publickey", ?MODULE, publickey_msg, [Callback1]},
+ {"publickey", ?MODULE, publickey_msg,[Callback2]},
+ {"password", ?MODULE, password_msg, []},
+ {"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}
+ ];
+method_preference(Callback1, Callback2, false) ->
+ [{"publickey", ?MODULE, publickey_msg, [Callback1]},
+ {"publickey", ?MODULE, publickey_msg,[Callback2]},
+ {"password", ?MODULE, password_msg, []}
+ ].
+
+user_name(Opts) ->
+ Env = case os:type() of
+ {win32, _} ->
+ "USERNAME";
+ {unix, _} ->
+ "LOGNAME"
+ end,
+ case proplists:get_value(user, Opts, os:getenv(Env)) of
+ false ->
+ case os:getenv("USER") of
+ false ->
+ {error, no_user};
+ User ->
+ {ok, User}
+ end;
+ User ->
+ {ok, User}
+ end.
+
+check_password(User, Password, Opts) ->
+ %%?dbg(true, " ~p ~p ~p ~n", [User, Password, Opts]),
+ case proplists:get_value(pwdfun, Opts) of
+ undefined ->
+ Static = get_password_option(Opts, User),
+ Password == Static;
+ Cheker ->
+ Cheker(User, Password)
+ end.
+
+get_password_option(Opts, User) ->
+ Passwords = proplists:get_value(user_passwords, Opts, []),
+ case lists:keysearch(User, 1, Passwords) of
+ {value, {User, Pw}} -> Pw;
+ false -> proplists:get_value(password, Opts, false)
+ end.
+
+verify_sig(SessionId, User, Service, Alg, KeyBlob, SigWLen, Opts) ->
+ case ssh_file:lookup_user_key(User, Alg, Opts) of
+ {ok, OurKey} ->
+ {ok, Key} = ssh_file:decode_public_key_v2(KeyBlob, Alg),
+ case OurKey of
+ Key ->
+ NewSig = build_sig_data(SessionId,
+ User, Service, Alg, KeyBlob),
+ <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
+ <<?UINT32(AlgLen), _Alg:AlgLen/binary,
+ ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
+ M = alg_to_module(Alg),
+ M:verify(OurKey, NewSig, Sig);
+ _ ->
+ {error, key_unacceptable}
+ end;
+ Error -> Error
+ end.
+
+build_sig_data(SessionId, User, Service, Alg, KeyBlob) ->
+ Sig = [?binary(SessionId),
+ ?SSH_MSG_USERAUTH_REQUEST,
+ ?string(User),
+ ?string(Service),
+ ?binary(<<"publickey">>),
+ ?TRUE,
+ ?string(Alg),
+ ?binary(KeyBlob)],
+ list_to_binary(Sig).
+
+decode_keyboard_interactive_prompts(NumPrompts, Data) ->
+ Types = lists:append(lists:duplicate(NumPrompts, [string, boolean])),
+ pairwise_tuplify(ssh_bits:decode(Data, Types)).
+
+pairwise_tuplify([E1, E2 | Rest]) -> [{E1, E2} | pairwise_tuplify(Rest)];
+pairwise_tuplify([]) -> [].
+
+
+keyboard_interact_get_responses(IoCb, Opts, Name, Instr, PromptInfos) ->
+ NumPrompts = length(PromptInfos),
+ case proplists:get_value(keyboard_interact_fun, Opts) of
+ undefined when NumPrompts == 1 ->
+ %% Special case/fallback for just one prompt
+ %% (assumed to be the password prompt)
+ case proplists:get_value(password, Opts) of
+ undefined -> keyboard_interact(IoCb, Name, Instr, PromptInfos);
+ PW -> [PW]
+ end;
+ undefined ->
+ keyboard_interact(IoCb, Name, Instr, PromptInfos);
+ KbdInteractFun ->
+ Prompts = lists:map(fun({Prompt, _Echo}) -> Prompt end,
+ PromptInfos),
+ case KbdInteractFun(Name, Instr, Prompts) of
+ Rs when length(Rs) == NumPrompts ->
+ Rs;
+ Rs ->
+ erlang:error({mismatching_number_of_responses,
+ {got,Rs},
+ {expected,NumPrompts}})
+ end
+ end.
+
+keyboard_interact(IoCb, Name, Instr, Prompts) ->
+ if Name /= "" -> IoCb:format("~s", [Name]);
+ true -> ok
+ end,
+ if Instr /= "" -> IoCb:format("~s", [Instr]);
+ true -> ok
+ end,
+ lists:map(fun({Prompt, true}) -> IoCb:read_line(Prompt);
+ ({Prompt, false}) -> IoCb:read_password(Prompt)
+ end,
+ Prompts).
+
+userauth_passwd_messages() ->
+ [
+ {ssh_msg_userauth_passwd_changereq, ?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ,
+ [string,
+ string]}
+ ].
+
+userauth_keyboard_interactive_messages() ->
+ [ {ssh_msg_userauth_info_request, ?SSH_MSG_USERAUTH_INFO_REQUEST,
+ [string,
+ string,
+ string,
+ uint32,
+ '...']},
+
+ {ssh_msg_userauth_info_response, ?SSH_MSG_USERAUTH_INFO_RESPONSE,
+ [uint32,
+ '...']}
+ ].
+
+userauth_pk_messages() ->
+ [ {ssh_msg_userauth_pk_ok, ?SSH_MSG_USERAUTH_PK_OK,
+ [string, % algorithm name
+ binary]} % key blob
+ ].
+
+alg_to_module("ssh-dss") ->
+ ssh_dsa;
+alg_to_module("ssh-rsa") ->
+ ssh_rsa.
+
+other_cb(ssh_rsa) ->
+ ssh_dsa;
+other_cb(ssh_dsa) ->
+ ssh_rsa.
diff --git a/lib/ssh/src/ssh_auth.hrl b/lib/ssh/src/ssh_auth.hrl
new file mode 100644
index 0000000000..80c5a6819b
--- /dev/null
+++ b/lib/ssh/src/ssh_auth.hrl
@@ -0,0 +1,83 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: Ssh User Authentication Protocol
+
+-define(SUPPORTED_AUTH_METHODS, "publickey,keyboard_interactive,password").
+
+-define(PREFERRED_PK_ALG, ssh_rsa).
+
+-define(SSH_MSG_USERAUTH_REQUEST, 50).
+-define(SSH_MSG_USERAUTH_FAILURE, 51).
+-define(SSH_MSG_USERAUTH_SUCCESS, 52).
+-define(SSH_MSG_USERAUTH_BANNER, 53).
+-define(SSH_MSG_USERAUTH_PK_OK, 60).
+-define(SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 60).
+-define(SSH_MSG_USERAUTH_INFO_REQUEST, 60).
+-define(SSH_MSG_USERAUTH_INFO_RESPONSE, 61).
+
+-record(ssh_msg_userauth_request,
+ {
+ user, %% string
+ service, %% string
+ method, %% string "publickey", "password"
+ data %% opaque
+ }).
+
+-record(ssh_msg_userauth_failure,
+ {
+ authentications, %% string
+ partial_success %% boolean
+ }).
+
+-record(ssh_msg_userauth_success,
+ {
+ }).
+
+-record(ssh_msg_userauth_banner,
+ {
+ message, %% string
+ language %% string
+ }).
+
+-record(ssh_msg_userauth_passwd_changereq,
+ {
+ prompt, %% string
+ languge %% string
+ }).
+
+-record(ssh_msg_userauth_pk_ok,
+ {
+ algorithm_name, % string
+ key_blob % string
+ }).
+
+-record(ssh_msg_userauth_info_request,
+ {name,
+ instruction,
+ language_tag,
+ num_prompts,
+ data}).
+
+-record(ssh_msg_userauth_info_response,
+ {num_responses,
+ data}).
+
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
new file mode 100755
index 0000000000..21ddc5e8fe
--- /dev/null
+++ b/lib/ssh/src/ssh_bits.erl
@@ -0,0 +1,483 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description : SSH 1/2 pdu elements encode/decode
+
+-module(ssh_bits).
+
+-include("ssh.hrl").
+
+-export([encode/1, encode/2]).
+-export([decode/1, decode/2, decode/3]).
+-export([mpint/1, bignum/1, string/1, name_list/1]).
+-export([b64_encode/1, b64_decode/1]).
+-export([install_messages/1, uninstall_messages/1]).
+
+%% integer utils
+-export([isize/1]).
+-export([irandom/1, irandom/3]).
+-export([random/1, random/3]).
+-export([xor_bits/2, fill_bits/2]).
+-export([i2bin/2, bin2i/1]).
+
+-import(lists, [foreach/2, reverse/1]).
+
+-define(name_list(X),
+ (fun(B) -> ?binary(B) end)(list_to_binary(name_concat(X)))).
+
+
+name_concat([Name]) when is_atom(Name) -> atom_to_list(Name);
+name_concat([Name]) when is_list(Name) -> Name;
+name_concat([Name|Ns]) ->
+ if is_atom(Name) ->
+ [atom_to_list(Name),"," | name_concat(Ns)];
+ is_list(Name) ->
+ [Name,"," | name_concat(Ns)]
+ end;
+name_concat([]) -> [].
+
+
+name_list(Ns) ->
+ ?name_list(Ns).
+
+
+string(Str) ->
+ ?string(Str).
+
+
+%% MP representaion (SSH2)
+mpint(X) when X < 0 ->
+ if X == -1 ->
+ <<0,0,0,1,16#ff>>;
+ true ->
+ mpint_neg(X,0,[])
+ end;
+mpint(X) ->
+ if X == 0 ->
+ <<0,0,0,0>>;
+ true ->
+ mpint_pos(X,0,[])
+ end.
+
+mpint_neg(-1,I,Ds=[MSB|_]) ->
+ if MSB band 16#80 =/= 16#80 ->
+ <<?UINT32((I+1)), (list_to_binary([255|Ds]))/binary>>;
+ true ->
+ (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
+ end;
+mpint_neg(X,I,Ds) ->
+ mpint_neg(X bsr 8,I+1,[(X band 255)|Ds]).
+
+mpint_pos(0,I,Ds=[MSB|_]) ->
+ if MSB band 16#80 == 16#80 ->
+ <<?UINT32((I+1)), (list_to_binary([0|Ds]))/binary>>;
+ true ->
+ (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
+ end;
+mpint_pos(X,I,Ds) ->
+ mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]).
+
+
+%% BIGNUM representation SSH1
+bignum(X) ->
+ XSz = isize(X),
+ Pad = (8 - (XSz rem 8)) rem 8,
+ <<?UINT16(XSz),0:Pad/unsigned-integer,X:XSz/big-unsigned-integer>>.
+
+
+install_messages(Codes) ->
+ foreach(fun({Name, Code, Ts}) ->
+ %% ?dbg(true, "install msg: ~s = ~w ~w~n",
+%% [Name,Code,Ts]),
+ put({msg_name,Code}, {Name,Ts}),
+ put({msg_code,Name}, {Code,Ts})
+ end, Codes).
+
+uninstall_messages(Codes) ->
+ foreach(fun({Name, Code, _Ts}) ->
+ %% ?dbg(true, "uninstall msg: ~s = ~w ~w~n",
+%% [Name,Code,_Ts]),
+ erase({msg_name,Code}),
+ erase({msg_code,Name})
+ end, Codes).
+
+%%
+%% Encode a record, the type spec is expected to be
+%% in process dictionary under the key {msg_code, RecodeName}
+%%
+encode(Record) ->
+ case get({msg_code, element(1, Record)}) of
+ undefined ->
+ {error, unimplemented};
+ {Code, Ts} ->
+ Data = enc(tl(tuple_to_list(Record)), Ts),
+ list_to_binary([Code, Data])
+ end.
+
+encode(List, Types) ->
+ list_to_binary(enc(List, Types)).
+
+%%
+%% Encode record element
+%%
+enc(Xs, Ts) ->
+ enc(Xs, Ts, 0).
+
+enc(Xs, [Type|Ts], Offset) ->
+ case Type of
+ boolean ->
+ X=hd(Xs),
+ [?boolean(X) | enc(tl(Xs), Ts, Offset+1)];
+ byte ->
+ X=hd(Xs),
+ [?byte(X) | enc(tl(Xs), Ts,Offset+1)];
+ uint16 ->
+ X=hd(Xs),
+ [?uint16(X) | enc(tl(Xs), Ts,Offset+2)];
+ uint32 ->
+ X=hd(Xs),
+ [?uint32(X) | enc(tl(Xs), Ts,Offset+4)];
+ uint64 ->
+ X=hd(Xs),
+ [?uint64(X) | enc(tl(Xs), Ts,Offset+8)];
+ mpint ->
+ Y=mpint(hd(Xs)),
+ [Y | enc(tl(Xs), Ts,Offset+size(Y))];
+ bignum ->
+ Y=bignum(hd(Xs)),
+ [Y | enc(tl(Xs),Ts,Offset+size(Y))];
+ string ->
+ X0=hd(Xs),
+ Y=?string(X0),
+ [Y | enc(tl(Xs),Ts,Offset+size(Y))];
+ binary ->
+ X0=hd(Xs),
+ Y=?binary(X0),
+ [Y | enc(tl(Xs), Ts,Offset+size(Y))];
+ name_list ->
+ X0=hd(Xs),
+ Y=?name_list(X0),
+ [Y | enc(tl(Xs), Ts, Offset+size(Y))];
+ cookie ->
+ [random(16) | enc(tl(Xs), Ts, Offset+16)];
+ {pad,N} ->
+ K = (N - (Offset rem N)) rem N,
+ [fill_bits(K,0) | enc(Xs, Ts, Offset+K)];
+ '...' when Ts==[] ->
+ X=hd(Xs),
+ if is_binary(X) ->
+ [X];
+ is_list(X) ->
+ [list_to_binary(X)];
+ X==undefined ->
+ []
+ end
+ end;
+enc([], [],_) ->
+ [].
+
+
+
+%%
+%% Decode a SSH record the type is encoded as the first byte
+%% and the type spec MUST be installed in {msg_name, ID}
+%%
+
+decode(Binary = <<?BYTE(ID), _/binary>>) ->
+ case get({msg_name, ID}) of
+ undefined ->
+ {unknown, Binary};
+ {Name, Ts} ->
+ {_, Elems} = decode(Binary,1,Ts),
+ list_to_tuple([Name | Elems])
+ end.
+
+%%
+%% Decode a binary form offset 0
+%%
+
+decode(Binary, Types) when is_binary(Binary) andalso is_list(Types) ->
+ {_,Elems} = decode(Binary, 0, Types),
+ Elems.
+
+
+%%
+%% Decode a binary from byte offset Offset
+%% return {UpdatedOffset, DecodedElements}
+%%
+decode(Binary, Offset, Types) ->
+ decode(Binary, Offset, Types, []).
+
+decode(Binary, Offset, [Type|Ts], Acc) ->
+ case Type of
+ boolean ->
+ <<_:Offset/binary, ?BOOLEAN(X0), _/binary>> = Binary,
+ X = if X0 == 0 -> false; true -> true end,
+ decode(Binary, Offset+1, Ts, [X | Acc]);
+
+ byte ->
+ <<_:Offset/binary, ?BYTE(X), _/binary>> = Binary,
+ decode(Binary, Offset+1, Ts, [X | Acc]);
+
+ uint16 ->
+ <<_:Offset/binary, ?UINT16(X), _/binary>> = Binary,
+ decode(Binary, Offset+2, Ts, [X | Acc]);
+
+ uint32 ->
+ <<_:Offset/binary, ?UINT32(X), _/binary>> = Binary,
+ decode(Binary, Offset+4, Ts, [X | Acc]);
+
+ uint64 ->
+ <<_:Offset/binary, ?UINT64(X), _/binary>> = Binary,
+ decode(Binary, Offset+8, Ts, [X | Acc]);
+
+ mpint ->
+ <<_:Offset/binary, ?UINT32(L), X0:L/binary,_/binary>> = Binary,
+ Sz = L*8,
+ <<X:Sz/big-signed-integer>> = X0,
+ decode(Binary, Offset+4+L, Ts, [X | Acc]);
+
+ bignum ->
+ <<_:Offset/binary, ?UINT16(Bits),_/binary>> = Binary,
+ L = (Bits+7) div 8,
+ Pad = (8 - (Bits rem 8)) rem 8,
+ <<_:Offset/binary, _:16, _:Pad, X:Bits/big-unsigned-integer,
+ _/binary>> = Binary,
+ decode(Binary, Offset+2+L, Ts, [X | Acc]);
+
+ string ->
+ Size = size(Binary),
+ if Size < Offset + 4 ->
+ %% empty string at end
+ {Size, reverse(["" | Acc])};
+ true ->
+ <<_:Offset/binary,?UINT32(L), X:L/binary,_/binary>> =
+ Binary,
+ decode(Binary, Offset+4+L, Ts, [binary_to_list(X) |
+ Acc])
+ end;
+
+ binary ->
+ <<_:Offset/binary,?UINT32(L), X:L/binary,_/binary>> = Binary,
+ decode(Binary, Offset+4+L, Ts, [X | Acc]);
+
+ name_list ->
+ <<_:Offset/binary,?UINT32(L), X:L/binary,_/binary>> = Binary,
+ List = string:tokens(binary_to_list(X), ","),
+ decode(Binary, Offset+4+L, Ts, [List | Acc]);
+
+ cookie ->
+ <<_:Offset/binary, X:16/binary, _/binary>> = Binary,
+ decode(Binary, Offset+16, Ts, [X | Acc]);
+
+ {pad,N} -> %% pad offset to a multiple of N
+ K = (N - (Offset rem N)) rem N,
+ decode(Binary, Offset+K, Ts, Acc);
+
+
+ '...' when Ts==[] ->
+ <<_:Offset/binary, X/binary>> = Binary,
+ {Offset+size(X), reverse([X | Acc])}
+ end;
+decode(_Binary, Offset, [], Acc) ->
+ {Offset, reverse(Acc)}.
+
+
+
+%% HACK WARNING :-)
+-define(VERSION_MAGIC, 131).
+-define(SMALL_INTEGER_EXT, $a).
+-define(INTEGER_EXT, $b).
+-define(SMALL_BIG_EXT, $n).
+-define(LARGE_BIG_EXT, $o).
+
+isize(N) when N > 0 ->
+ case term_to_binary(N) of
+ <<?VERSION_MAGIC, ?SMALL_INTEGER_EXT, X>> ->
+ isize_byte(X);
+ <<?VERSION_MAGIC, ?INTEGER_EXT, X3,X2,X1,X0>> ->
+ isize_bytes([X3,X2,X1,X0]);
+ <<?VERSION_MAGIC, ?SMALL_BIG_EXT, S:8/big-unsigned-integer, 0,
+ Ds:S/binary>> ->
+ K = S - 1,
+ <<_:K/binary, Top>> = Ds,
+ isize_byte(Top)+K*8;
+ <<?VERSION_MAGIC, ?LARGE_BIG_EXT, S:32/big-unsigned-integer, 0,
+ Ds:S/binary>> ->
+ K = S - 1,
+ <<_:K/binary, Top>> = Ds,
+ isize_byte(Top)+K*8
+ end;
+isize(0) -> 0.
+
+%% big endian byte list
+isize_bytes([0|L]) ->
+ isize_bytes(L);
+isize_bytes([Top|L]) ->
+ isize_byte(Top) + length(L)*8.
+
+%% Well could be improved
+isize_byte(X) ->
+ if X >= 2#10000000 -> 8;
+ X >= 2#1000000 -> 7;
+ X >= 2#100000 -> 6;
+ X >= 2#10000 -> 5;
+ X >= 2#1000 -> 4;
+ X >= 2#100 -> 3;
+ X >= 2#10 -> 2;
+ X >= 2#1 -> 1;
+ true -> 0
+ end.
+
+%% Convert integer into binary
+%% When XLen is the wanted size in octets of the output
+i2bin(X, XLen) ->
+ XSz = isize(X),
+ Sz = XLen*8,
+ if Sz < XSz ->
+ exit(integer_to_large);
+ true ->
+ (<<X:Sz/big-unsigned-integer>>)
+ end.
+
+%% Convert a binary into an integer
+%%
+bin2i(X) ->
+ Sz = size(X)*8,
+ <<Y:Sz/big-unsigned-integer>> = X,
+ Y.
+
+%%
+%% Create a binary with constant bytes
+%%
+fill_bits(N,C) ->
+ list_to_binary(fill(N,C)).
+
+fill(0,_C) -> [];
+fill(1,C) -> [C];
+fill(N,C) ->
+ Cs = fill(N div 2, C),
+ Cs1 = [Cs,Cs],
+ if N band 1 == 0 ->
+ Cs1;
+ true ->
+ [C,Cs,Cs]
+ end.
+
+%% xor 2 binaries
+xor_bits(XBits, YBits) ->
+ XSz = size(XBits)*8,
+ YSz = size(YBits)*8,
+ Sz = if XSz < YSz -> XSz; true -> YSz end, %% min
+ <<X:Sz, _/binary>> = XBits,
+ <<Y:Sz, _/binary>> = YBits,
+ <<(X bxor Y):Sz>>.
+
+%%
+%% irandom(N)
+%%
+%% Generate a N bits size random number
+%% note that the top most bit is always set
+%% to guarantee that the number is N bits
+%%
+irandom(Bits) ->
+ irandom(Bits, 1, 0).
+
+%% irandom_odd(Bits) ->
+%% irandom(Bits, 1, 1).
+
+%%
+%% irandom(N, Top, Bottom)
+%%
+%% Generate a N bits size random number
+%% Where Top = 0 - do not set top bit
+%% = 1 - set the most significant bit
+%% = 2 - set two most significant bits
+%% Bot = 0 - do not set the least signifcant bit
+%% Bot = 1 - set the least signifcant bit (i.e always odd)
+%%
+irandom(0, _Top, _Bottom) ->
+ 0;
+irandom(Bits, Top, Bottom) ->
+ Bytes = (Bits+7) div 8,
+ Skip = (8-(Bits rem 8)) rem 8,
+ TMask = case Top of
+ 0 -> 0;
+ 1 -> 16#80;
+ 2 -> 16#c0
+ end,
+ BMask = case Bottom of
+ 0 -> 0;
+ 1 -> (1 bsl Skip)
+ end,
+ <<X:Bits/big-unsigned-integer, _:Skip>> = random(Bytes, TMask, BMask),
+ X.
+
+%%
+%% random/1
+%% Generate N random bytes
+%%
+random(N) ->
+ random(N, 0, 0).
+
+random(N, TMask, BMask) ->
+ list_to_binary(rnd(N, TMask, BMask)).
+
+%% random/3
+%% random(Bytes, TopMask, BotMask)
+%% where
+%% Bytes is the number of bytes to generate
+%% TopMask is bitwised or'ed to the first byte
+%% BotMask is bitwised or'ed to the last byte
+%%
+rnd(0, _TMask, _BMask) ->
+ [];
+rnd(1, TMask, BMask) ->
+ [(rand8() bor TMask) bor BMask];
+rnd(N, TMask, BMask) ->
+ [(rand8() bor TMask) | rnd_n(N-1, BMask)].
+
+rnd_n(1, BMask) ->
+ [rand8() bor BMask];
+rnd_n(I, BMask) ->
+ [rand8() | rnd_n(I-1, BMask)].
+
+rand8() ->
+ (rand32() bsr 8) band 16#ff.
+
+rand32() ->
+ random:uniform(16#100000000) -1.
+
+%%
+%% Base 64 encode/decode
+%%
+
+b64_encode(Bs) when is_list(Bs) ->
+ base64:encode(Bs);
+b64_encode(Bin) when is_binary(Bin) ->
+ base64:encode(Bin).
+
+b64_decode(Bin) when is_binary(Bin) ->
+ base64:mime_decode(Bin);
+b64_decode(Cs) when is_list(Cs) ->
+ base64:mime_decode(Cs).
+
+
diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl
new file mode 100644
index 0000000000..3d67065ee1
--- /dev/null
+++ b/lib/ssh/src/ssh_channel.erl
@@ -0,0 +1,328 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_channel).
+
+-include("ssh_connect.hrl").
+
+-behaviour(gen_server).
+
+%%% API
+-export([behaviour_info/1, start/4, start/5, start_link/4, start_link/5, call/2, call/3,
+ cast/2, reply/2, enter_loop/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+%% Internal application API
+-export([cache_create/0, cache_lookup/2, cache_update/2,
+ cache_delete/1, cache_delete/2, cache_foldl/3,
+ cache_find/2]).
+
+-record(state, {
+ cm,
+ channel_cb,
+ channel_state,
+ channel_id,
+ close_sent = false
+ }).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+%%% Optionel callbacks handle_call/3, handle_cast/2, handle_msg/2,
+%%% code_change/3
+behaviour_info(callbacks) ->
+ [
+ {init, 1},
+ {terminate, 2},
+ {handle_ssh_msg, 2},
+ {handle_msg, 2}
+ ].
+
+
+call(ChannelPid, Msg) ->
+ call(ChannelPid, Msg, infinity).
+
+call(ChannelPid, Msg, TimeOute) ->
+ try gen_server:call(ChannelPid, Msg, TimeOute) of
+ Result ->
+ Result
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{timeout, _} ->
+ {error, timeout}
+ end.
+
+
+cast(ChannelPid, Msg) ->
+ gen_server:cast(ChannelPid, Msg).
+
+
+reply(From, Msg) ->
+ gen_server:reply(From, Msg).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
+ start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+
+start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ Options = [{channel_cb, CallBack},
+ {channel_id, ChannelId},
+ {init_args, CbInitArgs},
+ {cm, ConnectionManager},
+ {exec, Exec}],
+ gen_server:start(?MODULE, [Options], []).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
+ start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ Options = [{channel_cb, CallBack},
+ {channel_id, ChannelId},
+ {init_args, CbInitArgs},
+ {cm, ConnectionManager},
+ {exec, Exec}],
+ gen_server:start_link(?MODULE, [Options], []).
+
+enter_loop(State) ->
+ gen_server:enter_loop(?MODULE, [], State).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init([Options]) ->
+ Cb = proplists:get_value(channel_cb, Options),
+ ConnectionManager = proplists:get_value(cm, Options),
+ ChannelId = proplists:get_value(channel_id, Options),
+ process_flag(trap_exit, true),
+ InitArgs =
+ case proplists:get_value(exec, Options) of
+ undefined ->
+ proplists:get_value(init_args, Options);
+ Exec ->
+ proplists:get_value(init_args, Options) ++ [Exec]
+ end,
+ try Cb:init(InitArgs) of
+ {ok, ChannelState} ->
+ State = #state{cm = ConnectionManager,
+ channel_cb = Cb,
+ channel_id = ChannelId,
+ channel_state = ChannelState},
+ self() ! {ssh_channel_up, ChannelId, ConnectionManager},
+ {ok, State};
+ {ok, ChannelState, Timeout} ->
+ State = #state{cm = ConnectionManager,
+ channel_cb = Cb,
+ channel_id = ChannelId,
+ channel_state = ChannelState},
+ self() ! {ssh_channel_up, ChannelId, ConnectionManager},
+ {ok, State, Timeout};
+ {stop, Why} ->
+ {stop, Why}
+ catch
+ _:Reason ->
+ {stop, Reason}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+handle_call(Request, From, #state{channel_cb = Module,
+ channel_state = ChannelState} = State) ->
+ try Module:handle_call(Request, From, ChannelState) of
+ Result ->
+ handle_cb_result(Result, State)
+ catch
+ error:{undef, _} ->
+ {noreply, State}
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast(Msg, #state{channel_cb = Module,
+ channel_state = ChannelState} = State) ->
+
+ try Module:handle_cast(Msg, ChannelState) of
+ Result ->
+ handle_cb_result(Result, State)
+ catch
+ error:{undef, _} ->
+ {noreply, State}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info({ssh_cm, ConnectionManager, {closed, _ChannelId}},
+ #state{cm = ConnectionManager,
+ close_sent = true} = State) ->
+ {stop, normal, State};
+handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
+ #state{cm = ConnectionManager,
+ close_sent = false} = State) ->
+ %% To be on the safe side, i.e. the manager has already been terminated.
+ (catch ssh_connection:close(ConnectionManager, ChannelId)),
+ {stop, normal, State};
+
+handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
+ channel_cb = Module,
+ channel_state = ChannelState0} = State) ->
+ case Module:handle_ssh_msg(Msg, ChannelState0) of
+ {ok, ChannelState} ->
+ adjust_window(Msg),
+ {noreply, State#state{channel_state = ChannelState}};
+ {ok, ChannelState, Timeout} ->
+ adjust_window(Msg),
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+ {stop, ChannelId, ChannelState} ->
+ ssh_connection:close(ConnectionManager, ChannelId),
+ {stop, normal, State#state{close_sent = true,
+ channel_state = ChannelState}}
+ end;
+
+handle_info(Msg, #state{cm = ConnectionManager, channel_cb = Module,
+ channel_state = ChannelState0} = State) ->
+ case Module:handle_msg(Msg, ChannelState0) of
+ {ok, ChannelState} ->
+ {noreply, State#state{channel_state = ChannelState}};
+ {ok, ChannelState, Timeout} ->
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+ {stop, ChannelId, ChannelState} ->
+ ssh_connection:close(ConnectionManager, ChannelId),
+ {stop, normal, State#state{close_sent = true,
+ channel_state = ChannelState}}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(Reason, #state{cm = ConnectionManager,
+ channel_id = ChannelId,
+ close_sent = false} = State) ->
+ ssh_connection:close(ConnectionManager, ChannelId),
+ terminate(Reason, State#state{close_sent = true});
+terminate(_, #state{channel_cb = Cb, channel_state = ChannelState}) ->
+ catch Cb:terminate(Cb, ChannelState),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(OldVsn, #state{channel_cb = Module,
+ channel_state = ChannelState0} = State, Extra) ->
+ {ok, ChannelState} = Module:code_change(OldVsn, ChannelState0, Extra),
+ {ok, State#state{channel_state = ChannelState}}.
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+cache_create() ->
+ ets:new(cm_tab, [set,{keypos, #channel.local_id}]).
+
+cache_lookup(Cache, Key) ->
+ case ets:lookup(Cache, Key) of
+ [Channel] ->
+ Channel;
+ [] ->
+ undefined
+ end.
+
+cache_update(Cache, #channel{local_id = Id} = Entry) when Id =/= undefined ->
+ ets:insert(Cache, Entry).
+
+cache_delete(Cache, Key) ->
+ ets:delete(Cache, Key).
+
+cache_delete(Cache) ->
+ ets:delete(Cache).
+
+cache_foldl(Fun, Acc, Cache) ->
+ ets:foldl(Fun, Acc, Cache).
+
+cache_find(ChannelPid, Cache) ->
+ case ets:match_object(Cache, #channel{user = ChannelPid}) of
+ [] ->
+ undefined;
+ [Channel] ->
+ Channel
+ end.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+handle_cb_result({reply, Reply, ChannelState}, State) ->
+ {reply, Reply, State#state{channel_state = ChannelState}};
+handle_cb_result({reply, Reply, ChannelState, Timeout}, State) ->
+ {reply, Reply,State#state{channel_state = ChannelState}, Timeout};
+handle_cb_result({noreply, ChannelState}, State) ->
+ {noreply, State#state{channel_state = ChannelState}};
+handle_cb_result({noreply, ChannelState, Timeout}, State) ->
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+handle_cb_result({stop, Reason, Reply, ChannelState}, State) ->
+ {stop, Reason, Reply, State#state{channel_state = ChannelState}};
+handle_cb_result({stop, Reason, ChannelState}, State) ->
+ {stop, Reason, State#state{channel_state = ChannelState}}.
+
+adjust_window({ssh_cm, ConnectionManager,
+ {data, ChannelId, _, Data}}) ->
+ ssh_connection:adjust_window(ConnectionManager, ChannelId, size(Data));
+adjust_window(_) ->
+ ok.
+
+
diff --git a/lib/ssh/src/ssh_channel_sup.erl b/lib/ssh/src/ssh_channel_sup.erl
new file mode 100644
index 0000000000..c184fed627
--- /dev/null
+++ b/lib/ssh/src/ssh_channel_sup.erl
@@ -0,0 +1,54 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Ssh channel supervisor.
+%%----------------------------------------------------------------------
+-module(ssh_channel_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, start_child/2]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(Args) ->
+ supervisor:start_link(?MODULE, [Args]).
+
+start_child(Sup, ChildSpec) ->
+ supervisor:start_child(Sup, ChildSpec).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init(_Args) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = [],
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
new file mode 100644
index 0000000000..964f35121a
--- /dev/null
+++ b/lib/ssh/src/ssh_cli.erl
@@ -0,0 +1,500 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Description: a gen_server implementing a simple
+%% terminal (using the group module) for a CLI
+%% over SSH
+
+-module(ssh_cli).
+
+-behaviour(ssh_channel).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+
+%% ssh_channel callbacks
+-export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2]).
+
+%% backwards compatibility
+-export([listen/1, listen/2, listen/3, listen/4, stop/1]).
+
+%% state
+-record(state, {
+ cm,
+ channel,
+ pty,
+ group,
+ buf,
+ shell,
+ exec
+ }).
+
+%%====================================================================
+%% ssh_channel callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State}
+%%
+%% Description: Initiates the CLI
+%%--------------------------------------------------------------------
+init([Shell, Exec]) ->
+ {ok, #state{shell = Shell, exec = Exec}};
+init([Shell]) ->
+ {ok, #state{shell = Shell}}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles channel messages received on the ssh-connection.
+%%--------------------------------------------------------------------
+handle_ssh_msg({ssh_cm, _ConnectionManager,
+ {data, _ChannelId, _Type, Data}},
+ #state{group = Group} = State) ->
+ Group ! {self(), {data, binary_to_list(Data)}},
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, ConnectionManager,
+ {pty, ChannelId, WantReply,
+ {TermName, Width, Height, PixWidth, PixHeight, Modes}}},
+ State0) ->
+ State = State0#state{pty =
+ #ssh_pty{term = TermName,
+ width = not_zero(Width, 80),
+ height = not_zero(Height, 24),
+ pixel_width = PixWidth,
+ pixel_height = PixHeight,
+ modes = Modes}},
+ set_echo(State),
+ ssh_connection:reply_request(ConnectionManager, WantReply,
+ success, ChannelId),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, ConnectionManager,
+ {env, ChannelId, WantReply, _Var, _Value}}, State) ->
+ ssh_connection:reply_request(ConnectionManager,
+ WantReply, failure, ChannelId),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, ConnectionManager,
+ {window_change, ChannelId, Width, Height, PixWidth, PixHeight}},
+ #state{buf = Buf, pty = Pty0} = State) ->
+ Pty = Pty0#ssh_pty{width = Width, height = Height,
+ pixel_width = PixWidth,
+ pixel_height = PixHeight},
+ {Chars, NewBuf} = io_request({window_change, Pty0}, Buf, Pty),
+ write_chars(ConnectionManager, ChannelId, Chars),
+ {ok, State#state{pty = Pty, buf = NewBuf}};
+
+handle_ssh_msg({ssh_cm, ConnectionManager,
+ {shell, ChannelId, WantReply}}, State) ->
+ NewState = start_shell(ConnectionManager, State),
+ ssh_connection:reply_request(ConnectionManager, WantReply,
+ success, ChannelId),
+ {ok, NewState#state{channel = ChannelId,
+ cm = ConnectionManager}};
+
+handle_ssh_msg({ssh_cm, ConnectionManager,
+ {exec, ChannelId, WantReply, Cmd}}, #state{exec=undefined} = State) ->
+ {Reply, Status} = exec(Cmd),
+ write_chars(ConnectionManager,
+ ChannelId, io_lib:format("~p\n", [Reply])),
+ ssh_connection:reply_request(ConnectionManager, WantReply,
+ success, ChannelId),
+ ssh_connection:exit_status(ConnectionManager, ChannelId, Status),
+ ssh_connection:send_eof(ConnectionManager, ChannelId),
+ {stop, ChannelId, State#state{channel = ChannelId, cm = ConnectionManager}};
+handle_ssh_msg({ssh_cm, ConnectionManager,
+ {exec, ChannelId, WantReply, Cmd}}, State) ->
+ NewState = start_shell(ConnectionManager, Cmd, State),
+ ssh_connection:reply_request(ConnectionManager, WantReply,
+ success, ChannelId),
+ {ok, NewState#state{channel = ChannelId,
+ cm = ConnectionManager}};
+
+handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) ->
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
+ %% Ignore signals according to RFC 4254 section 6.9.
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}}, State) ->
+ Report = io_lib:format("Connection closed by peer ~n Error ~p~n",
+ [Error]),
+ error_logger:error_report(Report),
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, 0}}, State) ->
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State) ->
+
+ Report = io_lib:format("Connection closed by peer ~n Status ~p~n",
+ [Status]),
+ error_logger:error_report(Report),
+ {stop, ChannelId, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles other channel messages.
+%%--------------------------------------------------------------------
+handle_msg({ssh_channel_up, ChannelId, ConnectionManager},
+ #state{channel = ChannelId,
+ cm = ConnectionManager} = State) ->
+ {ok, State};
+
+handle_msg({Group, Req}, #state{group = Group, buf = Buf, pty = Pty,
+ cm = ConnectionManager,
+ channel = ChannelId} = State) ->
+ {Chars, NewBuf} = io_request(Req, Buf, Pty),
+ write_chars(ConnectionManager, ChannelId, Chars),
+ {ok, State#state{buf = NewBuf}};
+
+handle_msg({'EXIT', Group, _Reason}, #state{group = Group,
+ channel = ChannelId} = State) ->
+ {stop, ChannelId, State};
+
+handle_msg(_, State) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: Called when the channel process is trminated
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+exec(Cmd) ->
+ eval(parse(scan(Cmd))).
+
+scan(Cmd) ->
+ erl_scan:string(Cmd).
+
+parse({ok, Tokens, _}) ->
+ erl_parse:parse_exprs(Tokens);
+parse(Error) ->
+ Error.
+
+eval({ok, Expr_list}) ->
+ case (catch erl_eval:exprs(Expr_list,
+ erl_eval:new_bindings())) of
+ {value, Value, _NewBindings} ->
+ {Value, 0};
+ {'EXIT', {Error, _}} ->
+ {Error, -1};
+ Error ->
+ {Error, -1}
+ end;
+eval(Error) ->
+ {Error, -1}.
+
+%%% io_request, handle io requests from the user process,
+%%% Note, this is not the real I/O-protocol, but the mockup version
+%%% used between edlin and a user_driver. The protocol tags are
+%%% similar, but the message set is different.
+%%% The protocol only exists internally between edlin and a character
+%%% displaying device...
+%%% We are *not* really unicode aware yet, we just filter away characters
+%%% beyond the latin1 range. We however handle the unicode binaries...
+io_request({window_change, OldTty}, Buf, Tty) ->
+ window_change(Tty, OldTty, Buf);
+io_request({put_chars, Cs}, Buf, Tty) ->
+ put_chars(bin_to_list(Cs), Buf, Tty);
+io_request({put_chars, unicode, Cs}, Buf, Tty) ->
+ put_chars([Ch || Ch <- unicode:characters_to_list(Cs,unicode), Ch =< 255], Buf, Tty);
+io_request({insert_chars, Cs}, Buf, Tty) ->
+ insert_chars(bin_to_list(Cs), Buf, Tty);
+io_request({insert_chars, unicode, Cs}, Buf, Tty) ->
+ insert_chars([Ch || Ch <- unicode:characters_to_list(Cs,unicode), Ch =< 255], Buf, Tty);
+io_request({move_rel, N}, Buf, Tty) ->
+ move_rel(N, Buf, Tty);
+io_request({delete_chars,N}, Buf, Tty) ->
+ delete_chars(N, Buf, Tty);
+io_request(beep, Buf, _Tty) ->
+ {[7], Buf};
+
+%% New in R12
+io_request({get_geometry,columns},Buf,Tty) ->
+ {ok, Tty#ssh_pty.width, Buf};
+io_request({get_geometry,rows},Buf,Tty) ->
+ {ok, Tty#ssh_pty.height, Buf};
+io_request({requests,Rs}, Buf, Tty) ->
+ io_requests(Rs, Buf, Tty, []);
+io_request(tty_geometry, Buf, Tty) ->
+ io_requests([{move_rel, 0}, {put_chars, unicode, [10]}], Buf, Tty, []);
+ %{[], Buf};
+io_request(_R, Buf, _Tty) ->
+ {[], Buf}.
+
+io_requests([R|Rs], Buf, Tty, Acc) ->
+ {Chars, NewBuf} = io_request(R, Buf, Tty),
+ io_requests(Rs, NewBuf, Tty, [Acc|Chars]);
+io_requests([], Buf, _Tty, Acc) ->
+ {Acc, Buf}.
+
+%%% return commands for cursor navigation, assume everything is ansi
+%%% (vt100), add clauses for other terminal types if needed
+ansi_tty(N, L) ->
+ ["\e[", integer_to_list(N), L].
+
+get_tty_command(up, N, _TerminalType) ->
+ ansi_tty(N, $A);
+get_tty_command(down, N, _TerminalType) ->
+ ansi_tty(N, $B);
+get_tty_command(right, N, _TerminalType) ->
+ ansi_tty(N, $C);
+get_tty_command(left, N, _TerminalType) ->
+ ansi_tty(N, $D).
+
+
+-define(PAD, 10).
+-define(TABWIDTH, 8).
+
+%% convert input characters to buffer and to writeout
+%% Note that the buf is reversed but the buftail is not
+%% (this is handy; the head is always next to the cursor)
+conv_buf([], AccBuf, AccBufTail, AccWrite, Col) ->
+ {AccBuf, AccBufTail, lists:reverse(AccWrite), Col};
+conv_buf([13, 10 | Rest], _AccBuf, AccBufTail, AccWrite, _Col) ->
+ conv_buf(Rest, [], tl2(AccBufTail), [10, 13 | AccWrite], 0);
+conv_buf([13 | Rest], _AccBuf, AccBufTail, AccWrite, _Col) ->
+ conv_buf(Rest, [], tl1(AccBufTail), [13 | AccWrite], 0);
+conv_buf([10 | Rest], _AccBuf, AccBufTail, AccWrite, _Col) ->
+ conv_buf(Rest, [], tl1(AccBufTail), [10, 13 | AccWrite], 0);
+conv_buf([C | Rest], AccBuf, AccBufTail, AccWrite, Col) ->
+ conv_buf(Rest, [C | AccBuf], tl1(AccBufTail), [C | AccWrite], Col + 1).
+
+
+%%% put characters at current position (possibly overwriting
+%%% characters after current position in buffer)
+put_chars(Chars, {Buf, BufTail, Col}, _Tty) ->
+ {NewBuf, NewBufTail, WriteBuf, NewCol} =
+ conv_buf(Chars, Buf, BufTail, [], Col),
+ {WriteBuf, {NewBuf, NewBufTail, NewCol}}.
+
+%%% insert character at current position
+insert_chars([], {Buf, BufTail, Col}, _Tty) ->
+ {[], {Buf, BufTail, Col}};
+insert_chars(Chars, {Buf, BufTail, Col}, Tty) ->
+ {NewBuf, _NewBufTail, WriteBuf, NewCol} =
+ conv_buf(Chars, Buf, [], [], Col),
+ M = move_cursor(NewCol + length(BufTail), NewCol, Tty),
+ {[WriteBuf, BufTail | M], {NewBuf, BufTail, NewCol}}.
+
+%%% delete characters at current position, (backwards if negative argument)
+delete_chars(0, {Buf, BufTail, Col}, _Tty) ->
+ {[], {Buf, BufTail, Col}};
+delete_chars(N, {Buf, BufTail, Col}, Tty) when N > 0 ->
+ NewBufTail = nthtail(N, BufTail),
+ M = move_cursor(Col + length(NewBufTail) + N, Col, Tty),
+ {[NewBufTail, lists:duplicate(N, $ ) | M],
+ {Buf, NewBufTail, Col}};
+delete_chars(N, {Buf, BufTail, Col}, Tty) -> % N < 0
+ NewBuf = nthtail(-N, Buf),
+ NewCol = Col + N,
+ M1 = move_cursor(Col, NewCol, Tty),
+ M2 = move_cursor(NewCol + length(BufTail) - N, NewCol, Tty),
+ {[M1, BufTail, lists:duplicate(-N, $ ) | M2],
+ {NewBuf, BufTail, NewCol}}.
+
+%%% Window change, redraw the current line (and clear out after it
+%%% if current window is wider than previous)
+window_change(Tty, OldTty, Buf)
+ when OldTty#ssh_pty.width == Tty#ssh_pty.width ->
+ {[], Buf};
+window_change(Tty, OldTty, {Buf, BufTail, Col}) ->
+ M1 = move_cursor(Col, 0, OldTty),
+ N = max(Tty#ssh_pty.width - OldTty#ssh_pty.width, 0) * 2,
+ S = lists:reverse(Buf, [BufTail | lists:duplicate(N, $ )]),
+ M2 = move_cursor(length(Buf) + length(BufTail) + N, Col, Tty),
+ {[M1, S | M2], {Buf, BufTail, Col}}.
+
+%% move around in buffer, respecting pad characters
+step_over(0, Buf, [?PAD | BufTail], Col) ->
+ {[?PAD | Buf], BufTail, Col+1};
+step_over(0, Buf, BufTail, Col) ->
+ {Buf, BufTail, Col};
+step_over(N, [C | Buf], BufTail, Col) when N < 0 ->
+ N1 = ifelse(C == ?PAD, N, N+1),
+ step_over(N1, Buf, [C | BufTail], Col-1);
+step_over(N, Buf, [C | BufTail], Col) when N > 0 ->
+ N1 = ifelse(C == ?PAD, N, N-1),
+ step_over(N1, [C | Buf], BufTail, Col+1).
+
+%%% an empty line buffer
+empty_buf() -> {[], [], 0}.
+
+%%% col and row from position with given width
+col(N, W) -> N rem W.
+row(N, W) -> N div W.
+
+%%% move relative N characters
+move_rel(N, {Buf, BufTail, Col}, Tty) ->
+ {NewBuf, NewBufTail, NewCol} = step_over(N, Buf, BufTail, Col),
+ M = move_cursor(Col, NewCol, Tty),
+ {M, {NewBuf, NewBufTail, NewCol}}.
+
+%%% give move command for tty
+move_cursor(A, A, _Tty) ->
+ [];
+move_cursor(From, To, #ssh_pty{width=Width, term=Type}) ->
+ Tcol = case col(To, Width) - col(From, Width) of
+ 0 -> "";
+ I when I < 0 -> get_tty_command(left, -I, Type);
+ I -> get_tty_command(right, I, Type)
+ end,
+ Trow = case row(To, Width) - row(From, Width) of
+ 0 -> "";
+ J when J < 0 -> get_tty_command(up, -J, Type);
+ J -> get_tty_command(down, J, Type)
+ end,
+ [Tcol | Trow].
+
+%% %%% write out characters
+%% %%% make sure that there is data to send
+%% %%% before calling ssh_connection:send
+write_chars(ConnectionManager, ChannelId, Chars) ->
+ case erlang:iolist_size(Chars) of
+ 0 ->
+ ok;
+ _ ->
+ ssh_connection:send(ConnectionManager, ChannelId,
+ ?SSH_EXTENDED_DATA_DEFAULT, Chars)
+ end.
+
+%%% tail, works with empty lists
+tl1([_|A]) -> A;
+tl1(_) -> [].
+
+%%% second tail
+tl2([_,_|A]) -> A;
+tl2(_) -> [].
+
+%%% nthtail as in lists, but no badarg if n > the length of list
+nthtail(0, A) -> A;
+nthtail(N, [_ | A]) when N > 0 -> nthtail(N-1, A);
+nthtail(_, _) -> [].
+
+%%% utils
+max(A, B) when A > B -> A;
+max(_A, B) -> B.
+
+ifelse(Cond, A, B) ->
+ case Cond of
+ true -> A;
+ _ -> B
+ end.
+
+bin_to_list(B) when is_binary(B) ->
+ binary_to_list(B);
+bin_to_list(L) when is_list(L) ->
+ lists:flatten([bin_to_list(A) || A <- L]);
+bin_to_list(I) when is_integer(I) ->
+ I.
+
+start_shell(ConnectionManager, State) ->
+ Shell = State#state.shell,
+ ShellFun = case is_function(Shell) of
+ true ->
+ case erlang:fun_info(Shell, arity) of
+ {arity, 1} ->
+ {ok, User} =
+ ssh_userreg:lookup_user(ConnectionManager),
+ fun() -> Shell(User) end;
+ {arity, 2} ->
+ {ok, User} =
+ ssh_userreg:lookup_user(ConnectionManager),
+ {ok, PeerAddr} =
+ ssh_cm:get_peer_addr(ConnectionManager),
+ fun() -> Shell(User, PeerAddr) end;
+ _ ->
+ Shell
+ end;
+ _ ->
+ Shell
+ end,
+ Echo = get_echo(State#state.pty),
+ Group = group:start(self(), ShellFun, [{echo, Echo}]),
+ State#state{group = Group, buf = empty_buf()}.
+
+start_shell(_ConnectionManager, Cmd, #state{exec={M, F, A}} = State) ->
+ Group = group:start(self(), {M, F, A++[Cmd]}, [{echo,false}]),
+ State#state{group = Group, buf = empty_buf()}.
+
+
+% Pty can be undefined if the client never sets any pty options before
+% starting the shell.
+get_echo(undefined) ->
+ true;
+get_echo(#ssh_pty{modes = Modes}) ->
+ case proplists:get_value(echo, Modes, 1) of
+ 0 ->
+ false;
+ _ ->
+ true
+ end.
+
+% Group is undefined if the pty options are sent between open and
+% shell messages.
+set_echo(#state{group = undefined}) ->
+ ok;
+set_echo(#state{group = Group, pty = Pty}) ->
+ Echo = get_echo(Pty),
+ Group ! {self(), echo, Echo}.
+
+not_zero(0, B) ->
+ B;
+not_zero(A, _) ->
+ A.
+
+%%% Backwards compatibility
+
+%%--------------------------------------------------------------------
+%% Function: listen(...) -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts a listening server
+%% Note that the pid returned is NOT the pid of this gen_server;
+%% this server is started when an SSH connection is made on the
+%% listening port
+%%--------------------------------------------------------------------
+listen(Shell) ->
+ listen(Shell, 22).
+
+listen(Shell, Port) ->
+ listen(Shell, Port, []).
+
+listen(Shell, Port, Opts) ->
+ listen(Shell, any, Port, Opts).
+
+listen(Shell, HostAddr, Port, Opts) ->
+ ssh:daemon(HostAddr, Port, [{shell, Shell} | Opts]).
+
+
+%%--------------------------------------------------------------------
+%% Function: stop(Pid) -> ok
+%% Description: Stops the listener
+%%--------------------------------------------------------------------
+stop(Pid) ->
+ ssh:stop_listener(Pid).
diff --git a/lib/ssh/src/ssh_cm.erl b/lib/ssh/src/ssh_cm.erl
new file mode 100755
index 0000000000..c4d535df9a
--- /dev/null
+++ b/lib/ssh/src/ssh_cm.erl
@@ -0,0 +1,237 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description : Backwards compatibility wrapper
+
+-module(ssh_cm).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+
+%% -define(DEFAULT_PACKET_SIZE, 32768).
+%% -define(DEFAULT_WINDOW_SIZE, 2*?DEFAULT_PACKET_SIZE).
+%%-define(DEFAULT_TIMEOUT, 5000).
+
+-export([connect/1, connect/2, connect/3]).
+-export([listen/2, listen/3, listen/4, stop_listener/1]).
+-export([stop/1]).
+
+-deprecated({connect, 1, next_major_release}).
+-deprecated({connect, 2, next_major_release}).
+-deprecated({connect, 3, next_major_release}).
+-deprecated({listen, 2, next_major_release}).
+-deprecated({listen, 3, next_major_release}).
+-deprecated({listen, 4, next_major_release}).
+-deprecated({stop_listener, 1, next_major_release}).
+-deprecated({stop, 1, next_major_release}).
+
+-export([adjust_window/3, attach/2, attach/3, detach/2,
+ tcpip_forward/3, cancel_tcpip_forward/3, direct_tcpip/6,
+ direct_tcpip/8, close/2, shell/2, exec/4,
+ send/3, send/4,
+ send_ack/3, send_ack/4, send_ack/5, send_eof/2,
+ session_open/2, session_open/4, subsystem/4,
+ open_pty/3, open_pty/7, open_pty/9,
+ set_user_ack/4,
+ setenv/5, signal/3, winch/4]).
+
+-deprecated({adjust_window, 3, next_major_release}).
+-deprecated({attach, 2, next_major_release}).
+-deprecated({attach, 3, next_major_release}).
+-deprecated({detach, 2, next_major_release}).
+-deprecated({tcpip_forward, 3, next_major_release}).
+-deprecated({cancel_tcpip_forward, 3, next_major_release}).
+-deprecated({direct_tcpip, 6, next_major_release}).
+-deprecated({direct_tcpip, 8, next_major_release}).
+-deprecated({close, 2, next_major_release}).
+-deprecated({shell, 2, next_major_release}).
+-deprecated({exec, 4, next_major_release}).
+-deprecated({send, 3, next_major_release}).
+-deprecated({send, 4, next_major_release}).
+-deprecated({send_ack, 3, next_major_release}).
+-deprecated({send_ack, 4, next_major_release}).
+-deprecated({send_ack, 5, next_major_release}).
+-deprecated({send_eof, 2, next_major_release}).
+-deprecated({session_open, 2, next_major_release}).
+-deprecated({session_open, 4, next_major_release}).
+-deprecated({subsystem, 4, next_major_release}).
+-deprecated({open_pty, 3, next_major_release}).
+-deprecated({open_pty, 7, next_major_release}).
+-deprecated({open_pty, 9, next_major_release}).
+-deprecated({set_user_ack, 4, next_major_release}).
+-deprecated({setenv, 5, next_major_release}).
+-deprecated({signal, 3, next_major_release}).
+-deprecated({winch, 4, next_major_release}).
+
+-export([info/1, info/2, recv_window/3,
+ send_window/3, renegotiate/1, renegotiate/2,
+ get_peer_addr/1]).
+
+%%====================================================================
+%% API
+%%====================================================================
+connect(Host) ->
+ connect(Host, []).
+connect(Host, Opts) ->
+ connect(Host, ?SSH_DEFAULT_PORT, Opts).
+connect(Host, Port, Opts) ->
+ ssh:connect(Host, Port, Opts).
+
+listen(ChannelSpec, Port) ->
+ listen(ChannelSpec, Port, []).
+listen(ChannelSpec, Port, Opts) ->
+ listen(ChannelSpec, any, Port, Opts).
+listen(ChannelSpec, "localhost", Port, Opts) ->
+ listen(ChannelSpec, any, Port, Opts);
+listen(_ChannelSpec, Host, Port, Opts) ->
+ ssh:daemon(Host, Port, Opts).
+
+stop_listener(SysSup) ->
+ ssh_system_sup:stop_listener(SysSup).
+stop(Cm) ->
+ ssh:close(Cm).
+
+%% CM Client commands
+session_open(Cm, Timeout) ->
+ session_open(Cm, ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE, Timeout).
+
+session_open(Cm, InitialWindowSize, MaxPacketSize, Timeout) ->
+ ssh_connection:session_channel(Cm, InitialWindowSize, MaxPacketSize,
+ Timeout).
+
+
+setenv(Cm, Channel, Var, Value, Timeout) ->
+ ssh_connection:setenv(Cm, Channel, Var, Value, Timeout).
+
+shell(Cm, Channel) ->
+ ssh_connection:shell(Cm, Channel).
+
+exec(Cm, Channel, Command, Timeout) ->
+ ssh_connection:exec(Cm, Channel, Command, Timeout).
+
+subsystem(Cm, Channel, SubSystem, Timeout) ->
+ ssh_connection:subsystem(Cm, Channel, SubSystem, Timeout).
+
+%% Not needed for backwards compatibility for now
+attach(_Cm, _Timeout) ->
+ ok.
+
+attach(_Cm, _ChannelPid, _Timeout) ->
+ ok.
+
+detach(_Cm, _Timeout) ->
+ ok.
+
+%% Not needed, send_ack is now call! Temp backwardcompability
+set_user_ack(_, _, _, _) ->
+ ok.
+
+adjust_window(Cm, Channel, Bytes) ->
+ ssh_connection:adjust_window(Cm, Channel, Bytes).
+
+close(Cm, Channel) ->
+ ssh_connection:close(Cm, Channel).
+
+send_eof(Cm, Channel) ->
+ ssh_connection:send_eof(Cm, Channel).
+
+send(Cm, Channel, Data) ->
+ ssh_connection:send(Cm, Channel, 0, Data).
+
+send(Cm, Channel, Type, Data) ->
+ ssh_connection:send(Cm, Channel, Type, Data).
+
+%% Send ack is not needed
+send_ack(Cm, Channel, Data) ->
+ send_ack(Cm, Channel, 0, Data, infinity).
+
+send_ack(Cm, Channel, Type, Data) ->
+ send_ack(Cm, Channel, Type, Data, infinity).
+
+send_ack(Cm, Channel, Type, Data, Timeout) ->
+ ssh_connection:send(Cm, Channel, Type, Data, Timeout).
+
+%% ----------------------------------------------------------------------
+%% These functions replacers are not officially supported but proably will be
+%% when we had time to test them.
+%% ----------------------------------------------------------------------
+direct_tcpip(Cm, RemoteHost, RemotePort, OrigIP, OrigPort, Timeout) ->
+ direct_tcpip(Cm, RemoteHost, RemotePort, OrigIP, OrigPort,
+ ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE, Timeout).
+
+direct_tcpip(Cm, RemoteIP, RemotePort, OrigIP, OrigPort,
+ InitialWindowSize, MaxPacketSize, Timeout) ->
+ ssh_connection:direct_tcpip(Cm, RemoteIP, RemotePort,
+ OrigIP, OrigPort,
+ InitialWindowSize,
+ MaxPacketSize, Timeout).
+
+tcpip_forward(Cm, BindIP, BindPort) ->
+ ssh_connection:tcpip_forward(Cm, BindIP, BindPort).
+
+cancel_tcpip_forward(Cm, BindIP, Port) ->
+ ssh_connection:cancel_tcpip_forward(Cm, BindIP, Port).
+
+open_pty(Cm, Channel, Timeout) ->
+ open_pty(Cm, Channel, os:getenv("TERM"), 80, 24, [], Timeout).
+
+open_pty(Cm, Channel, Term, Width, Height, PtyOpts, Timeout) ->
+ open_pty(Cm, Channel, Term, Width, Height, 0, 0, PtyOpts, Timeout).
+
+open_pty(Cm, Channel, Term, Width, Height, PixWidth, PixHeight,
+ PtyOpts, Timeout) ->
+ ssh_connection:open_pty(Cm, Channel, Term,
+ Width, Height, PixWidth,
+ PixHeight, PtyOpts, Timeout).
+winch(Cm, Channel, Width, Height) ->
+ winch(Cm, Channel, Width, Height, 0, 0).
+winch(Cm, Channel, Width, Height, PixWidth, PixHeight) ->
+ ssh_connection:window_change(Cm, Channel, Width,
+ Height, PixWidth, PixHeight).
+signal(Cm, Channel, Sig) ->
+ ssh_connection:signal(Cm, Channel, Sig).
+
+%% ----------------------------------------------------------------------
+%% These functions replacers are not officially supported and
+%% the format of them will proably change when and
+%% if they get supported.
+%% ----------------------------------------------------------------------
+info(Cm) ->
+ info(Cm, all).
+
+info(Cm, ChannelPid) ->
+ ssh_connection_manager:info(Cm, ChannelPid).
+
+send_window(Cm, Channel, Timeout) ->
+ ssh_connection_manager:send_window(Cm, Channel, Timeout).
+
+recv_window(Cm, Channel, Timeout) ->
+ ssh_connection_manager:recv_window(Cm, Channel, Timeout).
+
+renegotiate(Cm) ->
+ renegotiate(Cm, []).
+renegotiate(Cm, _Opts) ->
+ %%TODO: How should this work, backwards compat?
+ ssh_connection_manager:renegotiate(Cm).
+
+get_peer_addr(Cm) ->
+ ssh_connection_manager:peer_addr(Cm).
+
diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl
new file mode 100755
index 0000000000..a5a4e42cd8
--- /dev/null
+++ b/lib/ssh/src/ssh_connect.hrl
@@ -0,0 +1,264 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description : SSH connection protocol
+
+-define(DEFAULT_PACKET_SIZE, 32768).
+-define(DEFAULT_WINDOW_SIZE, 2*?DEFAULT_PACKET_SIZE).
+-define(DEFAULT_TIMEOUT, 5000).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% CONNECT messages
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%----------------------------------------------------------------------
+%%% # SSH_MSG_xxx
+%%% Description: Packet types used by the connection protocol.
+%%%----------------------------------------------------------------------
+-define(SSH_MSG_GLOBAL_REQUEST, 80).
+-define(SSH_MSG_REQUEST_SUCCESS, 81).
+-define(SSH_MSG_REQUEST_FAILURE, 82).
+-define(SSH_MSG_CHANNEL_OPEN, 90).
+-define(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 91).
+-define(SSH_MSG_CHANNEL_OPEN_FAILURE, 92).
+-define(SSH_MSG_CHANNEL_WINDOW_ADJUST, 93).
+-define(SSH_MSG_CHANNEL_DATA, 94).
+-define(SSH_MSG_CHANNEL_EXTENDED_DATA, 95).
+-define(SSH_MSG_CHANNEL_EOF, 96).
+-define(SSH_MSG_CHANNEL_CLOSE, 97).
+-define(SSH_MSG_CHANNEL_REQUEST, 98).
+-define(SSH_MSG_CHANNEL_SUCCESS, 99).
+-define(SSH_MSG_CHANNEL_FAILURE, 100).
+
+-record(ssh_msg_global_request,
+ {
+ name,
+ want_reply,
+ data %% ...
+ }).
+
+-record(ssh_msg_request_success,
+ {
+ data %% ...
+ }).
+
+-record(ssh_msg_request_failure,
+ {
+ }).
+
+
+-record(ssh_msg_channel_open,
+ {
+ channel_type,
+ sender_channel,
+ initial_window_size,
+ maximum_packet_size,
+ data %% ...
+ }).
+
+-record(ssh_msg_channel_open_confirmation,
+ {
+ recipient_channel,
+ sender_channel,
+ initial_window_size,
+ maximum_packet_size,
+ data %% ...
+ }).
+
+
+%%%----------------------------------------------------------------------
+%%% # SSH_OPEN_xxx
+%%% Description: Reason codes for SSH_MSG_OPEN_FAILURE packages.
+%%%----------------------------------------------------------------------
+
+-define(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, 1).
+-define(SSH_OPEN_CONNECT_FAILED, 2).
+-define(SSH_OPEN_UNKNOWN_CHANNEL_TYPE, 3).
+-define(SSH_OPEN_RESOURCE_SHORTAGE, 4).
+
+-record(ssh_msg_channel_open_failure,
+ {
+ recipient_channel,
+ reason,
+ description,
+ lang
+ }).
+
+
+-record(ssh_msg_channel_window_adjust,
+ {
+ recipient_channel,
+ bytes_to_add
+ }).
+
+-record(ssh_msg_channel_data,
+ {
+ recipient_channel,
+ data
+ }).
+
+%%%----------------------------------------------------------------------
+%%% # SSH_EXTENDED_DATA_xxx
+%%% Description: Type codes for SSH_MSG_CHANNEL_EXTENDED_DATA packages
+%%%----------------------------------------------------------------------
+-define(SSH_EXTENDED_DATA_DEFAULT, 0).
+-define(SSH_EXTENDED_DATA_STDERR, 1).
+
+-record(ssh_msg_channel_extended_data,
+ {
+ recipient_channel,
+ data_type_code,
+ data
+ }).
+
+-record(ssh_msg_channel_eof,
+ {
+ recipient_channel
+ }).
+
+-record(ssh_msg_channel_close,
+ {
+ recipient_channel
+ }).
+
+
+-record(ssh_msg_channel_request,
+ {
+ recipient_channel,
+ request_type,
+ want_reply,
+ data %% ...
+ }).
+
+
+-record(ssh_msg_channel_success,
+ {
+ recipient_channel
+ }).
+
+
+-record(ssh_msg_channel_failure,
+ {
+ recipient_channel
+ }).
+
+-define(TTY_OP_END,0). %% Indicates end of options.
+-define(VINTR,1). %% Interrupt character; 255 if none. Similarly for the
+ %% other characters. Not all of these characters are
+ %% supported on all systems.
+-define(VQUIT,2). %% The quit character (sends SIGQUIT signal on POSIX
+ %% systems).
+-define(VERASE,3). %% Erase the character to left of the cursor.
+-define(VKILL,4). %% Kill the current input line.
+-define(VEOF,5). %% End-of-file character (sends EOF from the terminal).
+-define(VEOL,6). %% End-of-line character in addition to carriage return
+ %% or,and). linefeed.
+-define(VEOL2,7). %% Additional end-of-line character.
+-define(VSTART,8). %% Continues paused output (normally control-Q).
+-define(VSTOP,9). %% Pauses output (normally control-S).
+-define(VSUSP,10). %% Suspends the current program.
+-define(VDSUSP,11). %% Another suspend character.
+-define(VREPRINT,12). %% Reprints the current input line.
+-define(VWERASE,13). %% Erases a word left of cursor.
+-define(VLNEXT,14). %% Enter the next character typed literally, even if it
+ %% is a special character
+-define(VFLUSH,15). %% Character to flush output.
+-define(VSWTCH,16). %% Switch to a different shell layer.
+-define(VSTATUS,17). %% Prints system status line (load, command, pid etc).
+-define(VDISCARD,18). %% Toggles the flushing of terminal output.
+-define(IGNPAR,30). %% The ignore parity flag. The parameter SHOULD be 0 if
+ %% this flag is FALSE set, and 1 if it is TRUE.
+-define(PARMRK,31). %% Mark parity and framing errors.
+-define(INPCK,32). %% Enable checking of parity errors.
+-define(ISTRIP,33). %% Strip 8th bit off characters.
+-define(INLCR,34). %% Map NL into CR on input.
+-define(IGNCR,35). %% Ignore CR on input.
+-define(ICRNL,36). %% Map CR to NL on input.
+-define(IUCLC,37). %% Translate uppercase characters to lowercase.
+-define(IXON,38). %% Enable output flow control.
+-define(IXANY,39). %% Any char will restart after stop.
+-define(IXOFF,40). %% Enable input flow control.
+-define(IMAXBEL,41). %% Ring bell on input queue full.
+-define(ISIG,50). %% Enable signals INTR, QUIT, [D]SUSP.
+-define(ICANON,51). %% Canonicalize input lines.
+-define(XCASE,52). %% Enable input and output of uppercase characters by
+ %% preceding their lowercase equivalents with `\'.
+-define(ECHO,53). %% Enable echoing.
+-define(ECHOE,54). %% Visually erase chars.
+-define(ECHOK,55). %% Kill character discards current line.
+-define(ECHONL,56). %% Echo NL even if ECHO is off.
+-define(NOFLSH,57). %% Don't flush after interrupt.
+-define(TOSTOP,58). %% Stop background jobs from output.
+-define(IEXTEN,59). %% Enable extensions.
+-define(ECHOCTL,60). %% Echo control characters as ^(Char).
+-define(ECHOKE,61). %% Visual erase for line kill.
+-define(PENDIN,62). %% Retype pending input.
+-define(OPOST,70). %% Enable output processing.
+-define(OLCUC,71). %% Convert lowercase to uppercase.
+-define(ONLCR,72). %% Map NL to CR-NL.
+-define(OCRNL,73). %% Translate carriage return to newline (output).
+-define(ONOCR,74). %% Translate newline to carriage return-newline
+ %% (output).
+-define(ONLRET,75). %% Newline performs a carriage return (output).
+-define(CS7,90). %% 7 bit mode.
+-define(CS8,91). %% 8 bit mode.
+-define(PARENB,92). %% Parity enable.
+-define(PARODD,93). %% Odd parity, else even.
+
+%% Specifies the input baud rate in bits per second.
+-define(TTY_OP_ISPEED,128).
+%% Specifies the output baud rate in bits per second.
+-define(TTY_OP_OSPEED,129).
+
+-record(channel,
+ {
+ type, %% "session", "x11", "forwarded-tcpip", "direct-tcpip"
+ sys, %% "none", "shell", "exec" "subsystem"
+ user, %% "user" process id (default to cm user)
+ flow_control,
+
+ local_id, %% local channel id
+
+ recv_window_size,
+ recv_packet_size,
+ recv_close = false,
+
+ remote_id, %% remote channel id
+ send_window_size,
+ send_packet_size,
+ sent_close = false,
+ send_buf = []
+ }).
+
+-record(connection, {
+ requests = [], %% [{ChannelId, Pid}...] awaiting reply on request,
+ channel_cache,
+ channel_pids = [],
+ port_bindings,
+ channel_id_seed,
+ cli_spec,
+ address,
+ port,
+ options,
+ exec
+ }).
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
new file mode 100644
index 0000000000..0aaf1c18d2
--- /dev/null
+++ b/lib/ssh/src/ssh_connection.erl
@@ -0,0 +1,1366 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose: Details of connection protocol
+%%----------------------------------------------------------------------
+
+-module(ssh_connection).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+-include("ssh_transport.hrl").
+
+-export([session_channel/2, session_channel/4,
+ exec/4, shell/2, subsystem/4, send/3, send/4, send/5,
+ send_eof/2, adjust_window/3, open_pty/3, open_pty/7,
+ open_pty/9, setenv/5, window_change/4, window_change/6,
+ direct_tcpip/6, direct_tcpip/8, tcpip_forward/3,
+ cancel_tcpip_forward/3, signal/3, exit_status/3, encode_ip/1, close/2,
+ reply_request/4]).
+
+-export([channel_data/6, handle_msg/4, channel_eof_msg/1,
+ channel_close_msg/1, channel_success_msg/1, channel_failure_msg/1,
+ channel_adjust_window_msg/2, channel_data_msg/3,
+ channel_open_msg/5, channel_open_confirmation_msg/4,
+ channel_open_failure_msg/4, channel_request_msg/4,
+ global_request_msg/3, request_failure_msg/0,
+ request_success_msg/1, bind/4, unbind/3, unbind_channel/2,
+ bound_channel/3, messages/0]).
+
+%%--------------------------------------------------------------------
+%%% Internal application API
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: session_channel(ConnectionManager
+%% [, InitialWindowSize, MaxPacketSize],
+%% Timeout) -> {ok, }
+%% ConnectionManager = pid()
+%% InitialWindowSize = integer()
+%% MaxPacketSize = integer()
+%%
+%% Description: Opens a channel for a ssh session. A session is a
+%% remote execution of a program. The program may be a shell, an
+%% application, a system command, or some built-in subsystem.
+%% --------------------------------------------------------------------
+session_channel(ConnectionManager, Timeout) ->
+ session_channel(ConnectionManager,
+ ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE,
+ Timeout).
+session_channel(ConnectionManager, InitialWindowSize,
+ MaxPacketSize, Timeout) ->
+ ssh_connection_manager:open_channel(ConnectionManager, "session", <<>>,
+ InitialWindowSize,
+ MaxPacketSize, Timeout).
+%%--------------------------------------------------------------------
+%% Function: exec(ConnectionManager, ChannelId, Command, Timeout) ->
+%%
+%% ConnectionManager = pid()
+%% ChannelId = integer()
+%% Cmd = string()
+%% Timeout = integer()
+%%
+%% Description: Will request that the server start the
+%% execution of the given command.
+%%--------------------------------------------------------------------
+exec(ConnectionManager, ChannelId, Command, TimeOut) ->
+ ssh_connection_manager:request(ConnectionManager, self(), ChannelId, "exec",
+ true, [?string(Command)], TimeOut).
+%%--------------------------------------------------------------------
+%% Function: shell(ConnectionManager, ChannelId) ->
+%%
+%% ConnectionManager = pid()
+%% ChannelId = integer()
+%%
+%% Description: Will request that the user's default shell (typically
+%% defined in /etc/passwd in UNIX systems) be started at the other
+%% end.
+%%--------------------------------------------------------------------
+shell(ConnectionManager, ChannelId) ->
+ ssh_connection_manager:request(ConnectionManager, self(), ChannelId,
+ "shell", false, <<>>, 0).
+%%--------------------------------------------------------------------
+%% Function: subsystem(ConnectionManager, ChannelId, SubSystem, TimeOut) ->
+%%
+%% ConnectionManager = pid()
+%% ChannelId = integer()
+%% SubSystem = string()
+%% TimeOut = integer()
+%%
+%%
+%% Description: Executes a predefined subsystem.
+%%--------------------------------------------------------------------
+subsystem(ConnectionManager, ChannelId, SubSystem, TimeOut) ->
+ ssh_connection_manager:request(ConnectionManager, self(),
+ ChannelId, "subsystem",
+ true, [?string(SubSystem)], TimeOut).
+%%--------------------------------------------------------------------
+%% Function: send(ConnectionManager, ChannelId, Type, Data, [TimeOut]) ->
+%%
+%%
+%% Description: Sends channel data.
+%%--------------------------------------------------------------------
+send(ConnectionManager, ChannelId, Data) ->
+ send(ConnectionManager, ChannelId, 0, Data, infinity).
+send(ConnectionManager, ChannelId, Data, TimeOut) when is_integer(TimeOut) ->
+ send(ConnectionManager, ChannelId, 0, Data, TimeOut);
+send(ConnectionManager, ChannelId, Type, Data) ->
+ send(ConnectionManager, ChannelId, Type, Data, infinity).
+send(ConnectionManager, ChannelId, Type, Data, TimeOut) ->
+ ssh_connection_manager:send(ConnectionManager, ChannelId,
+ Type, Data, TimeOut).
+%%--------------------------------------------------------------------
+%% Function: send_eof(ConnectionManager, ChannelId) ->
+%%
+%%
+%% Description: Sends eof on the channel <ChannelId>.
+%%--------------------------------------------------------------------
+send_eof(ConnectionManager, Channel) ->
+ ssh_connection_manager:send_eof(ConnectionManager, Channel).
+
+%%--------------------------------------------------------------------
+%% Function: adjust_window(ConnectionManager, Channel, Bytes) ->
+%%
+%%
+%% Description: Adjusts the ssh flowcontrol window.
+%%--------------------------------------------------------------------
+adjust_window(ConnectionManager, Channel, Bytes) ->
+ ssh_connection_manager:adjust_window(ConnectionManager, Channel, Bytes).
+
+%%--------------------------------------------------------------------
+%% Function: setenv(ConnectionManager, ChannelId, Var, Value, TimeOut) ->
+%%
+%%
+%% Description: Environment variables may be passed to the shell/command to be
+%% started later.
+%%--------------------------------------------------------------------
+setenv(ConnectionManager, ChannelId, Var, Value, TimeOut) ->
+ ssh_connection_manager:request(ConnectionManager, ChannelId,
+ "env", true, [?string(Var), ?string(Value)], TimeOut).
+
+
+%%--------------------------------------------------------------------
+%% Function: close(ConnectionManager, ChannelId) ->
+%%
+%%
+%% Description: Sends a close message on the channel <ChannelId>.
+%%--------------------------------------------------------------------
+close(ConnectionManager, ChannelId) ->
+ ssh_connection_manager:close(ConnectionManager, ChannelId).
+
+
+%%--------------------------------------------------------------------
+%% Function: reply_request(ConnectionManager, WantReply, Status, CannelId) ->_
+%%
+%%
+%% Description: Send status replies to requests that want such replies.
+%%--------------------------------------------------------------------
+reply_request(ConnectionManager, true, Status, ChannelId) ->
+ ConnectionManager ! {ssh_cm, self(), {Status, ChannelId}},
+ ok;
+reply_request(_,false, _, _) ->
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% Function: window_change(ConnectionManager, Channel, Width, Height) ->
+%%
+%%
+%% Description: Not yet officialy supported.
+%%--------------------------------------------------------------------
+window_change(ConnectionManager, Channel, Width, Height) ->
+ window_change(ConnectionManager, Channel, Width, Height, 0, 0).
+window_change(ConnectionManager, Channel, Width, Height,
+ PixWidth, PixHeight) ->
+ ssh_connection_manager:request(ConnectionManager, Channel,
+ "window-change", false,
+ [?uint32(Width), ?uint32(Height),
+ ?uint32(PixWidth), ?uint32(PixHeight)], 0).
+%%--------------------------------------------------------------------
+%% Function: signal(ConnectionManager, Channel, Sig) ->
+%%
+%%
+%% Description: Not yet officialy supported.
+%%--------------------------------------------------------------------
+signal(ConnectionManager, Channel, Sig) ->
+ ssh_connection_manager:request(ConnectionManager, Channel,
+ "signal", false, [?string(Sig)], 0).
+
+%%--------------------------------------------------------------------
+%% Function: signal(ConnectionManager, Channel, Status) ->
+%%
+%%
+%% Description: Not yet officialy supported.
+%%--------------------------------------------------------------------
+exit_status(ConnectionManager, Channel, Status) ->
+ ssh_connection_manager:request(ConnectionManager, Channel,
+ "exit-status", false, [?uint32(Status)], 0).
+
+
+%%--------------------------------------------------------------------
+%% Function: open_pty(ConnectionManager, Channel, TimeOut) ->
+%%
+%%
+%% Description: Not yet officialy supported.
+%%--------------------------------------------------------------------
+open_pty(ConnectionManager, Channel, TimeOut) ->
+ open_pty(ConnectionManager, Channel,
+ os:getenv("TERM"), 80, 24, [], TimeOut).
+
+open_pty(ConnectionManager, Channel, Term, Width, Height, PtyOpts, TimeOut) ->
+ open_pty(ConnectionManager, Channel, Term, Width,
+ Height, 0, 0, PtyOpts, TimeOut).
+
+open_pty(ConnectionManager, Channel, Term, Width, Height,
+ PixWidth, PixHeight, PtyOpts, TimeOut) ->
+ ssh_connection_manager:request(ConnectionManager,
+ Channel, "pty-req", true,
+ [?string(Term),
+ ?uint32(Width), ?uint32(Height),
+ ?uint32(PixWidth),?uint32(PixHeight),
+ encode_pty_opts(PtyOpts)], TimeOut).
+
+
+%%--------------------------------------------------------------------
+%% Function: direct_tcpip(ConnectionManager, RemoteHost,
+%% RemotePort, OrigIP, OrigPort, Timeout) ->
+%%
+%%
+%% Description: Not yet officialy supported.
+%%--------------------------------------------------------------------
+direct_tcpip(ConnectionManager, RemoteHost,
+ RemotePort, OrigIP, OrigPort, Timeout) ->
+ direct_tcpip(ConnectionManager, RemoteHost, RemotePort, OrigIP, OrigPort,
+ ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE, Timeout).
+
+direct_tcpip(ConnectionManager, RemoteIP, RemotePort, OrigIP, OrigPort,
+ InitialWindowSize, MaxPacketSize, Timeout) ->
+ case {encode_ip(RemoteIP), encode_ip(OrigIP)} of
+ {false, _} ->
+ {error, einval};
+ {_, false} ->
+ {error, einval};
+ {RIP, OIP} ->
+ ssh_connection_manager:open_channel(ConnectionManager,
+ "direct-tcpip",
+ [?string(RIP),
+ ?uint32(RemotePort),
+ ?string(OIP),
+ ?uint32(OrigPort)],
+ InitialWindowSize,
+ MaxPacketSize,
+ Timeout)
+ end.
+%%--------------------------------------------------------------------
+%% Function: tcpip_forward(ConnectionManager, BindIP, BindPort) ->
+%%
+%%
+%% Description: Not yet officialy supported.
+%%--------------------------------------------------------------------
+tcpip_forward(ConnectionManager, BindIP, BindPort) ->
+ case encode_ip(BindIP) of
+ false ->
+ {error, einval};
+ IPStr ->
+ ssh_connection_manager:global_request(ConnectionManager,
+ "tcpip-forward", true,
+ [?string(IPStr),
+ ?uint32(BindPort)])
+ end.
+%%--------------------------------------------------------------------
+%% Function: cancel_tcpip_forward(ConnectionManager, BindIP, Port) ->
+%%
+%%
+%% Description: Not yet officialy supported.
+%%--------------------------------------------------------------------
+cancel_tcpip_forward(ConnectionManager, BindIP, Port) ->
+ case encode_ip(BindIP) of
+ false ->
+ {error, einval};
+ IPStr ->
+ ssh_connection_manager:global_request(ConnectionManager,
+ "cancel-tcpip-forward", true,
+ [?string(IPStr),
+ ?uint32(Port)])
+ end.
+
+%%--------------------------------------------------------------------
+%%% Internal API
+%%--------------------------------------------------------------------
+channel_data(ChannelId, DataType, Data, Connection, ConnectionPid, From)
+ when is_list(Data)->
+ channel_data(ChannelId, DataType,
+ list_to_binary(Data), Connection, ConnectionPid, From);
+
+channel_data(ChannelId, DataType, Data,
+ #connection{channel_cache = Cache} = Connection, ConnectionPid,
+ From) ->
+
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{remote_id = Id} = Channel0 ->
+ {SendList, Channel} = update_send_window(Channel0, DataType,
+ Data, Connection),
+ Replies =
+ lists:map(fun({SendDataType, SendData}) ->
+ {connection_reply, ConnectionPid,
+ channel_data_msg(Id,
+ SendDataType,
+ SendData)}
+ end, SendList),
+ FlowCtrlMsgs = flow_control(Replies,
+ Channel#channel{flow_control = From},
+ Cache),
+ {{replies, Replies ++ FlowCtrlMsgs}, Connection};
+ undefined ->
+ {noreply, Connection}
+ end.
+
+handle_msg(#ssh_msg_channel_open_confirmation{recipient_channel = ChannelId,
+ sender_channel = RemoteId,
+ initial_window_size = WindowSz,
+ maximum_packet_size = PacketSz},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+
+ #channel{remote_id = undefined} = Channel =
+ ssh_channel:cache_lookup(Cache, ChannelId),
+
+ ssh_channel:cache_update(Cache, Channel#channel{
+ remote_id = RemoteId,
+ send_window_size = WindowSz,
+ send_packet_size = PacketSz}),
+ {Reply, Connection} = reply_msg(Channel, Connection0, {open, ChannelId}),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_open_failure{recipient_channel = ChannelId,
+ reason = Reason,
+ description = Descr,
+ lang = Lang},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ ssh_channel:cache_delete(Cache, ChannelId),
+ {Reply, Connection} =
+ reply_msg(Channel, Connection0, {open_error, Reason, Descr, Lang}),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_success{recipient_channel = ChannelId},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ {Reply, Connection} = reply_msg(Channel, Connection0, success),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_failure{recipient_channel = ChannelId},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ {Reply, Connection} = reply_msg(Channel, Connection0, failure),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_eof{recipient_channel = ChannelId},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ {Reply, Connection} = reply_msg(Channel, Connection0, {eof, ChannelId}),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_close{recipient_channel = ChannelId},
+ #connection{channel_cache = Cache} = Connection0,
+ ConnectionPid, _) ->
+
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{sent_close = Closed, remote_id = RemoteId} = Channel ->
+ ssh_channel:cache_delete(Cache, ChannelId),
+ {CloseMsg, Connection} =
+ reply_msg(Channel, Connection0, {closed, ChannelId}),
+ case Closed of
+ true ->
+ {{replies, [CloseMsg]}, Connection};
+ false ->
+ RemoteCloseMsg = channel_close_msg(RemoteId),
+ {{replies,
+ [{connection_reply,
+ ConnectionPid, RemoteCloseMsg},
+ CloseMsg]}, Connection}
+ end;
+ undefined ->
+ {{replies, []}, Connection0}
+ end;
+
+handle_msg(#ssh_msg_channel_data{recipient_channel = ChannelId,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+
+ #channel{recv_window_size = Size} = Channel =
+ ssh_channel:cache_lookup(Cache, ChannelId),
+ WantedSize = Size - size(Data),
+ ssh_channel:cache_update(Cache, Channel#channel{
+ recv_window_size = WantedSize}),
+ {Replies, Connection} =
+ channel_data_reply(Cache, Channel, Connection0, 0, Data),
+ {{replies, Replies}, Connection};
+
+handle_msg(#ssh_msg_channel_extended_data{recipient_channel = ChannelId,
+ data_type_code = DataType,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+
+ #channel{recv_window_size = Size} = Channel =
+ ssh_channel:cache_lookup(Cache, ChannelId),
+ WantedSize = Size - size(Data),
+ ssh_channel:cache_update(Cache, Channel#channel{
+ recv_window_size = WantedSize}),
+ {Replies, Connection} =
+ channel_data_reply(Cache, Channel, Connection0, DataType, Data),
+ {{replies, Replies}, Connection};
+
+handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId,
+ bytes_to_add = Add},
+ #connection{channel_cache = Cache} = Connection,
+ ConnectionPid, _) ->
+
+ #channel{send_window_size = Size} =
+ Channel0 = ssh_channel:cache_lookup(Cache, ChannelId),
+
+ {SendList, Channel} = %% TODO: Datatype 0 ?
+ update_send_window(Channel0#channel{send_window_size = Size + Add},
+ 0, <<>>, Connection),
+
+ Replies = lists:map(fun({Type, Data}) ->
+ {connection_reply, ConnectionPid,
+ channel_data_msg(ChannelId, Type, Data)}
+ end, SendList),
+ FlowCtrlMsgs = flow_control(Channel, Cache),
+ {{replies, Replies ++ FlowCtrlMsgs}, Connection};
+
+handle_msg(#ssh_msg_channel_open{channel_type = "session" = Type,
+ sender_channel = ChannelId,
+ initial_window_size = WindowSz,
+ maximum_packet_size = PacketSz}, Connection0,
+ ConnectionPid, server) ->
+
+ try setup_session(Connection0, ConnectionPid, ChannelId,
+ Type, WindowSz, PacketSz) of
+ Result ->
+ Result
+ catch _:_ ->
+ FailMsg = channel_open_failure_msg(ChannelId,
+ ?SSH_OPEN_CONNECT_FAILED,
+ "Connection refused", "en"),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
+ Connection0}
+ end;
+
+handle_msg(#ssh_msg_channel_open{channel_type = "session",
+ sender_channel = RemoteId},
+ Connection, ConnectionPid, client) ->
+ %% Client implementations SHOULD reject any session channel open
+ %% requests to make it more difficult for a corrupt server to attack the
+ %% client. See See RFC 4254 6.1.
+ FailMsg = channel_open_failure_msg(RemoteId,
+ ?SSH_OPEN_CONNECT_FAILED,
+ "Connection refused", "en"),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
+ Connection};
+
+handle_msg(#ssh_msg_channel_open{channel_type = "forwarded-tcpip" = Type,
+ sender_channel = RemoteId,
+ initial_window_size = RWindowSz,
+ maximum_packet_size = RPacketSz,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection0,
+ ConnectionPid, server) ->
+ <<?UINT32(ALen), Address:ALen/binary, ?UINT32(Port),
+ ?UINT32(OLen), Orig:OLen/binary, ?UINT32(OrigPort)>> = Data,
+
+ case bound_channel(Address, Port, Connection0) of
+ undefined ->
+ FailMsg = channel_open_failure_msg(RemoteId,
+ ?SSH_OPEN_CONNECT_FAILED,
+ "Connection refused", "en"),
+ {{replies,
+ [{connection_reply, ConnectionPid, FailMsg}]}, Connection0};
+ ChannelPid ->
+ {ChannelId, Connection1} = new_channel_id(Connection0),
+ LWindowSz = ?DEFAULT_WINDOW_SIZE,
+ LPacketSz = ?DEFAULT_PACKET_SIZE,
+ Channel = #channel{type = Type,
+ sys = "none",
+ user = ChannelPid,
+ local_id = ChannelId,
+ recv_window_size = LWindowSz,
+ recv_packet_size = LPacketSz,
+ send_window_size = RWindowSz,
+ send_packet_size = RPacketSz},
+ ssh_channel:cache_update(Cache, Channel),
+ OpenConfMsg = channel_open_confirmation_msg(RemoteId, ChannelId,
+ LWindowSz, LPacketSz),
+ {OpenMsg, Connection} =
+ reply_msg(Channel, Connection1,
+ {open, Channel, {forwarded_tcpip,
+ decode_ip(Address), Port,
+ decode_ip(Orig), OrigPort}}),
+ {{replies, [{connection_reply, ConnectionPid, OpenConfMsg},
+ OpenMsg]}, Connection}
+ end;
+
+handle_msg(#ssh_msg_channel_open{channel_type = "forwarded-tcpip",
+ sender_channel = RemoteId},
+ Connection, ConnectionPid, client) ->
+ %% Client implementations SHOULD reject direct TCP/IP open requests for
+ %% security reasons. See RFC 4254 7.2.
+ FailMsg = channel_open_failure_msg(RemoteId,
+ ?SSH_OPEN_CONNECT_FAILED,
+ "Connection refused", "en"),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]}, Connection};
+
+
+handle_msg(#ssh_msg_channel_open{sender_channel = ChannelId}, Connection,
+ ConnectionPid, _) ->
+ FailMsg = channel_open_failure_msg(ChannelId,
+ ?SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
+ "Not allowed", "en"),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "exit-status",
+ data = Data},
+ #connection{channel_cache = Cache} = Connection, _, _) ->
+ <<?UINT32(Status)>> = Data,
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ {Reply, Connection} =
+ reply_msg(Channel, Connection, {exit_status, ChannelId, Status}),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "exit-signal",
+ want_reply = false,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection0,
+ ConnectionPid, _) ->
+ <<?UINT32(SigLen), SigName:SigLen/binary,
+ ?BOOLEAN(_Core),
+ ?UINT32(ErrLen), Err:ErrLen/binary,
+ ?UINT32(LangLen), Lang:LangLen/binary>> = Data,
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ RemoteId = Channel#channel.remote_id,
+ {Reply, Connection} = reply_msg(Channel, Connection0,
+ {exit_signal, ChannelId,
+ binary_to_list(SigName),
+ binary_to_list(Err),
+ binary_to_list(Lang)}),
+ CloseMsg = channel_close_msg(RemoteId),
+ {{replies, [{connection_reply, ConnectionPid, CloseMsg}, Reply]},
+ Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "xon-xoff",
+ want_reply = false,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection, _, _) ->
+ <<?BOOLEAN(CDo)>> = Data,
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ {Reply, Connection} =
+ reply_msg(Channel, Connection, {xon_xoff, ChannelId, CDo=/= 0}),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "window-change",
+ want_reply = false,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+ <<?UINT32(Width),?UINT32(Height),
+ ?UINT32(PixWidth), ?UINT32(PixHeight)>> = Data,
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ {Reply, Connection} =
+ reply_msg(Channel, Connection0, {window_change, ChannelId,
+ Width, Height,
+ PixWidth, PixHeight}),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "signal",
+ data = Data},
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+ <<?UINT32(SigLen), SigName:SigLen/binary>> = Data,
+
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ {Reply, Connection} =
+ reply_msg(Channel, Connection0, {signal, ChannelId,
+ binary_to_list(SigName)}),
+ {{replies, [Reply]}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "subsystem",
+ want_reply = WantReply,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection,
+ ConnectionPid, server) ->
+ <<?UINT32(SsLen), SsName:SsLen/binary>> = Data,
+
+ #channel{remote_id = RemoteId} = Channel0 =
+ ssh_channel:cache_lookup(Cache, ChannelId),
+
+ ReplyMsg = {subsystem, ChannelId, WantReply, binary_to_list(SsName)},
+
+ try start_subsytem(SsName, Connection, Channel0, ReplyMsg) of
+ {ok, Pid} ->
+ erlang:monitor(process, Pid),
+ Channel = Channel0#channel{user = Pid},
+ ssh_channel:cache_update(Cache, Channel),
+ Reply = {connection_reply, ConnectionPid,
+ channel_success_msg(RemoteId)},
+ {{replies, [Reply]}, Connection}
+ catch _:_ ->
+ Reply = {connection_reply, ConnectionPid,
+ channel_failure_msg(RemoteId)},
+ {{replies, [Reply]}, Connection}
+ end;
+
+handle_msg(#ssh_msg_channel_request{request_type = "subsystem"},
+ Connection, _, client) ->
+ %% The client SHOULD ignore subsystem requests. See RFC 4254 6.5.
+ {{replies, []}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "pty-req",
+ want_reply = WantReply,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection,
+ ConnectionPid, server) ->
+ <<?UINT32(TermLen), BTermName:TermLen/binary,
+ ?UINT32(Width),?UINT32(Height),
+ ?UINT32(PixWidth), ?UINT32(PixHeight),
+ Modes/binary>> = Data,
+ TermName = binary_to_list(BTermName),
+
+ PtyRequest = {TermName, Width, Height,
+ PixWidth, PixHeight, decode_pty_opts(Modes)},
+
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+
+ handle_cli_msg(Connection, ConnectionPid, Channel,
+ {pty, ChannelId, WantReply, PtyRequest});
+
+handle_msg(#ssh_msg_channel_request{request_type = "pty-req"},
+ Connection, _, client) ->
+ %% The client SHOULD ignore pty requests. See RFC 4254 6.2.
+ {{replies, []}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "shell",
+ want_reply = WantReply},
+ #connection{channel_cache = Cache} = Connection,
+ ConnectionPid, server) ->
+
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+
+ handle_cli_msg(Connection, ConnectionPid, Channel,
+ {shell, ChannelId, WantReply});
+
+handle_msg(#ssh_msg_channel_request{request_type = "shell"},
+ Connection, _, client) ->
+ %% The client SHOULD ignore shell requests. See RFC 4254 6.5.
+ {{replies, []}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "exec",
+ want_reply = WantReply,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection,
+ ConnectionPid, server) ->
+ <<?UINT32(Len), Command:Len/binary>> = Data,
+
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+
+ handle_cli_msg(Connection, ConnectionPid, Channel,
+ {exec, ChannelId, WantReply, binary_to_list(Command)});
+
+handle_msg(#ssh_msg_channel_request{request_type = "exec"},
+ Connection, _, client) ->
+ %% The client SHOULD ignore exec requests. See RFC 4254 6.5.
+ {{replies, []}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = "env",
+ want_reply = WantReply,
+ data = Data},
+ #connection{channel_cache = Cache} = Connection,
+ ConnectionPid, server) ->
+
+ <<?UINT32(VarLen),
+ Var:VarLen/binary, ?UINT32(ValueLen), Value:ValueLen/binary>> = Data,
+
+ Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+
+ handle_cli_msg(Connection, ConnectionPid, Channel,
+ {env, ChannelId, WantReply, Var, Value});
+
+handle_msg(#ssh_msg_channel_request{request_type = "env"},
+ Connection, _, client) ->
+ %% The client SHOULD ignore env requests.
+ {{replies, []}, Connection};
+
+handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = _Other,
+ want_reply = WantReply}, Connection,
+ ConnectionPid, _) ->
+ ?dbg(true, "ssh_msg ssh_msg_channel_request: Other=~p\n",
+ [_Other]),
+ if WantReply == true ->
+ FailMsg = channel_failure_msg(ChannelId),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
+ Connection};
+ true ->
+ {noreply, Connection}
+ end;
+
+handle_msg(#ssh_msg_global_request{name = _Type,
+ want_reply = WantReply,
+ data = _Data}, Connection,
+ ConnectionPid, _) ->
+ if WantReply == true ->
+ FailMsg = request_failure_msg(),
+ {{replies, [{connection_reply, ConnectionPid, FailMsg}]},
+ Connection};
+ true ->
+ {noreply, Connection}
+ end;
+
+%%% This transport message will also be handled at the connection level
+handle_msg(#ssh_msg_disconnect{code = Code,
+ description = Description,
+ language = _Lang },
+ #connection{channel_cache = Cache} = Connection0, _, _) ->
+ {Connection, Replies} =
+ ssh_channel:cache_foldl(fun(Channel, {Connection1, Acc}) ->
+ {Reply, Connection2} =
+ reply_msg(Channel,
+ Connection1, {closed, Channel#channel.local_id}),
+ {Connection2, [Reply | Acc]}
+ end, {Connection0, []}, Cache),
+
+ ssh_channel:cache_delete(Cache),
+ {disconnect, {Code, Description}, {{replies, Replies}, Connection}}.
+
+handle_cli_msg(#connection{channel_cache = Cache} = Connection0,
+ ConnectionPid,
+ #channel{user = undefined,
+ local_id = ChannelId} = Channel0, Reply0) ->
+
+ case (catch start_cli(Connection0, ChannelId)) of
+ {ok, Pid} ->
+ erlang:monitor(process, Pid),
+ Channel = Channel0#channel{user = Pid},
+ ssh_channel:cache_update(Cache, Channel),
+ {Reply, Connection} = reply_msg(Channel, Connection0, Reply0),
+ {{replies, [Reply]}, Connection};
+ _ ->
+ Reply = {connection_reply, ConnectionPid,
+ request_failure_msg()},
+ {{replies, [Reply]}, Connection0}
+ end;
+
+handle_cli_msg(Connection0, _, Channel, Reply0) ->
+ {Reply, Connection} = reply_msg(Channel, Connection0, Reply0),
+ {{replies, [Reply]}, Connection}.
+
+
+channel_eof_msg(ChannelId) ->
+ #ssh_msg_channel_eof{recipient_channel = ChannelId}.
+
+channel_close_msg(ChannelId) ->
+ #ssh_msg_channel_close {recipient_channel = ChannelId}.
+
+channel_success_msg(ChannelId) ->
+ #ssh_msg_channel_success{recipient_channel = ChannelId}.
+
+channel_failure_msg(ChannelId) ->
+ #ssh_msg_channel_failure{recipient_channel = ChannelId}.
+
+channel_adjust_window_msg(ChannelId, Bytes) ->
+ #ssh_msg_channel_window_adjust{recipient_channel = ChannelId,
+ bytes_to_add = Bytes}.
+
+channel_data_msg(ChannelId, 0, Data) ->
+ #ssh_msg_channel_data{recipient_channel = ChannelId,
+ data = Data};
+channel_data_msg(ChannelId, Type, Data) ->
+ #ssh_msg_channel_extended_data{recipient_channel = ChannelId,
+ data_type_code = Type,
+ data = Data}.
+
+channel_open_msg(Type, ChannelId, WindowSize, MaxPacketSize, Data) ->
+ #ssh_msg_channel_open{channel_type = Type,
+ sender_channel = ChannelId,
+ initial_window_size = WindowSize,
+ maximum_packet_size = MaxPacketSize,
+ data = Data
+ }.
+
+channel_open_confirmation_msg(RemoteId, LID, WindowSize, PacketSize) ->
+ #ssh_msg_channel_open_confirmation{recipient_channel = RemoteId,
+ sender_channel = LID,
+ initial_window_size = WindowSize,
+ maximum_packet_size = PacketSize}.
+
+channel_open_failure_msg(RemoteId, Reason, Description, Lang) ->
+ #ssh_msg_channel_open_failure{recipient_channel = RemoteId,
+ reason = Reason,
+ description = Description,
+ lang = Lang}.
+
+channel_request_msg(ChannelId, Type, WantReply, Data) ->
+ #ssh_msg_channel_request{recipient_channel = ChannelId,
+ request_type = Type,
+ want_reply = WantReply,
+ data = Data}.
+
+global_request_msg(Type, WantReply, Data) ->
+ #ssh_msg_global_request{name = Type,
+ want_reply = WantReply,
+ data = Data}.
+request_failure_msg() ->
+ #ssh_msg_request_failure{}.
+
+request_success_msg(Data) ->
+ #ssh_msg_request_success{data = Data}.
+
+bind(IP, Port, ChannelPid, Connection) ->
+ Binds = [{{IP, Port}, ChannelPid}
+ | lists:keydelete({IP, Port}, 1,
+ Connection#connection.port_bindings)],
+ Connection#connection{port_bindings = Binds}.
+
+unbind(IP, Port, Connection) ->
+ Connection#connection{
+ port_bindings =
+ lists:keydelete({IP, Port}, 1,
+ Connection#connection.port_bindings)}.
+unbind_channel(ChannelPid, Connection) ->
+ Binds = [{Bind, ChannelP} || {Bind, ChannelP}
+ <- Connection#connection.port_bindings,
+ ChannelP =/= ChannelPid],
+ Connection#connection{port_bindings = Binds}.
+
+bound_channel(IP, Port, Connection) ->
+ case lists:keysearch({IP, Port}, 1, Connection#connection.port_bindings) of
+ {value, {{IP, Port}, ChannelPid}} -> ChannelPid;
+ _ -> undefined
+ end.
+
+messages() ->
+ [ {ssh_msg_global_request, ?SSH_MSG_GLOBAL_REQUEST,
+ [string,
+ boolean,
+ '...']},
+
+ {ssh_msg_request_success, ?SSH_MSG_REQUEST_SUCCESS,
+ ['...']},
+
+ {ssh_msg_request_failure, ?SSH_MSG_REQUEST_FAILURE,
+ []},
+
+ {ssh_msg_channel_open, ?SSH_MSG_CHANNEL_OPEN,
+ [string,
+ uint32,
+ uint32,
+ uint32,
+ '...']},
+
+ {ssh_msg_channel_open_confirmation, ?SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
+ [uint32,
+ uint32,
+ uint32,
+ uint32,
+ '...']},
+
+ {ssh_msg_channel_open_failure, ?SSH_MSG_CHANNEL_OPEN_FAILURE,
+ [uint32,
+ uint32,
+ string,
+ string]},
+
+ {ssh_msg_channel_window_adjust, ?SSH_MSG_CHANNEL_WINDOW_ADJUST,
+ [uint32,
+ uint32]},
+
+ {ssh_msg_channel_data, ?SSH_MSG_CHANNEL_DATA,
+ [uint32,
+ binary]},
+
+ {ssh_msg_channel_extended_data, ?SSH_MSG_CHANNEL_EXTENDED_DATA,
+ [uint32,
+ uint32,
+ binary]},
+
+ {ssh_msg_channel_eof, ?SSH_MSG_CHANNEL_EOF,
+ [uint32]},
+
+ {ssh_msg_channel_close, ?SSH_MSG_CHANNEL_CLOSE,
+ [uint32]},
+
+ {ssh_msg_channel_request, ?SSH_MSG_CHANNEL_REQUEST,
+ [uint32,
+ string,
+ boolean,
+ '...']},
+
+ {ssh_msg_channel_success, ?SSH_MSG_CHANNEL_SUCCESS,
+ [uint32]},
+
+ {ssh_msg_channel_failure, ?SSH_MSG_CHANNEL_FAILURE,
+ [uint32]}
+ ].
+
+encode_ip(Addr) when is_tuple(Addr) ->
+ case catch inet_parse:ntoa(Addr) of
+ {'EXIT',_} -> false;
+ A -> A
+ end;
+encode_ip(Addr) when is_list(Addr) ->
+ case inet_parse:address(Addr) of
+ {ok, _} -> Addr;
+ Error ->
+ case inet:getaddr(Addr, inet) of
+ {ok, A} ->
+ inet_parse:ntoa(A);
+ Error -> false
+ end
+ end.
+
+start_channel(Address, Port, Cb, Id, Args) ->
+ start_channel(Address, Port, Cb, Id, Args, undefined).
+
+start_channel(Address, Port, Cb, Id, Args, Exec) ->
+ ChildSpec = child_spec(Cb, Id, Args, Exec),
+ SystemSup = ssh_system_sup:system_supervisor(Address, Port),
+ ChannelSup = ssh_system_sup:channel_supervisor(SystemSup),
+ ssh_channel_sup:start_child(ChannelSup, ChildSpec).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+setup_session(#connection{channel_cache = Cache} = Connection0,
+ ConnectionPid, RemoteId,
+ Type, WindowSize, PacketSize) ->
+ {ChannelId, Connection} = new_channel_id(Connection0),
+
+ Channel = #channel{type = Type,
+ sys = "ssh",
+ local_id = ChannelId,
+ recv_window_size = ?DEFAULT_WINDOW_SIZE,
+ recv_packet_size = ?DEFAULT_PACKET_SIZE,
+ send_window_size = WindowSize,
+ send_packet_size = PacketSize,
+ remote_id = RemoteId
+ },
+ ssh_channel:cache_update(Cache, Channel),
+ OpenConfMsg = channel_open_confirmation_msg(RemoteId, ChannelId,
+ ?DEFAULT_WINDOW_SIZE,
+ ?DEFAULT_PACKET_SIZE),
+
+ {{replies, [{connection_reply, ConnectionPid, OpenConfMsg}]}, Connection}.
+
+
+check_subsystem("sftp"= SsName, Options) ->
+ case proplists:get_value(subsystems, Options, no_subsys) of
+ no_subsys ->
+ {SsName, {Cb, Opts}} = ssh_sftpd:subsystem_spec([]),
+ {Cb, Opts};
+ SubSystems ->
+ proplists:get_value(SsName, SubSystems, {none, []})
+ end;
+
+check_subsystem(SsName, Options) ->
+ Subsystems = proplists:get_value(subsystems, Options, []),
+ case proplists:get_value(SsName, Subsystems, {none, []}) of
+ Fun when is_function(Fun) ->
+ {Fun, []};
+ {_, _} = Value ->
+ Value
+ end.
+
+child_spec(Callback, Id, Args, Exec) ->
+ Name = make_ref(),
+ StartFunc = {ssh_channel, start_link, [self(), Id, Callback, Args, Exec]},
+ Restart = temporary,
+ Shutdown = 3600,
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, [ssh_channel]}.
+
+%% Backwards compatibility
+start_cli(#connection{address = Address, port = Port, cli_spec = {Fun, [Shell]},
+ options = Options},
+ _ChannelId) when is_function(Fun) ->
+ case Fun(Shell, Address, Port, Options) of
+ NewFun when is_function(NewFun) ->
+ {ok, NewFun()};
+ Pid when is_pid(Pid) ->
+ {ok, Pid}
+ end;
+
+start_cli(#connection{address = Address, port = Port,
+ cli_spec = {CbModule, Args}, exec = Exec}, ChannelId) ->
+ start_channel(Address, Port, CbModule, ChannelId, Args, Exec).
+
+start_subsytem(BinName, #connection{address = Address, port = Port,
+ options = Options},
+ #channel{local_id = ChannelId, remote_id = RemoteChannelId},
+ ReplyMsg) ->
+ Name = binary_to_list(BinName),
+ case check_subsystem(Name, Options) of
+ {Callback, Opts} when is_atom(Callback), Callback =/= none ->
+ start_channel(Address, Port, Callback, ChannelId, Opts);
+ {Other, _} when Other =/= none ->
+ handle_backwards_compatibility(Other, self(),
+ ChannelId, RemoteChannelId,
+ Options, Address, Port,
+ {ssh_cm, self(), ReplyMsg})
+ end.
+
+channel_data_reply(_, #channel{local_id = ChannelId} = Channel,
+ Connection0, DataType, Data) ->
+ {Reply, Connection} =
+ reply_msg(Channel, Connection0, {data, ChannelId, DataType, Data}),
+ {[Reply], Connection}.
+
+new_channel_id(Connection) ->
+ ID = Connection#connection.channel_id_seed,
+ {ID, Connection#connection{channel_id_seed = ID + 1}}.
+
+reply_msg(Channel, Connection, {open, _} = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, {open_error, _, _, _} = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, success = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, failure = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, {closed, _} = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(#channel{user = ChannelPid}, Connection, Reply) ->
+ {{channel_data, ChannelPid, Reply}, Connection}.
+
+request_reply_or_data(#channel{local_id = ChannelId, user = ChannelPid},
+ #connection{requests = Requests} =
+ Connection, Reply) ->
+ case lists:keysearch(ChannelId, 1, Requests) of
+ {value, {ChannelId, From}} ->
+ {{channel_requst_reply, From, Reply},
+ Connection#connection{requests =
+ lists:keydelete(ChannelId, 1, Requests)}};
+ false ->
+ {{channel_data, ChannelPid, Reply}, Connection}
+ end.
+
+update_send_window(Channel0, DataType, Data,
+ #connection{channel_cache = Cache}) ->
+ Buf0 = if Data == <<>> ->
+ Channel0#channel.send_buf;
+ true ->
+ Channel0#channel.send_buf ++ [{DataType, Data}]
+ end,
+ {Buf1, NewSz, Buf2} = get_window(Buf0,
+ Channel0#channel.send_packet_size,
+ Channel0#channel.send_window_size),
+
+ Channel = Channel0#channel{send_window_size = NewSz, send_buf = Buf2},
+ ssh_channel:cache_update(Cache, Channel),
+ {Buf1, Channel}.
+
+get_window(Bs, PSz, WSz) ->
+ get_window(Bs, PSz, WSz, []).
+
+get_window(Bs, _PSz, 0, Acc) ->
+ {lists:reverse(Acc), 0, Bs};
+get_window([B0 = {DataType, Bin} | Bs], PSz, WSz, Acc) ->
+ BSz = size(Bin),
+ if BSz =< WSz -> %% will fit into window
+ if BSz =< PSz -> %% will fit into a packet
+ get_window(Bs, PSz, WSz-BSz, [B0|Acc]);
+ true -> %% split into packet size
+ <<Bin1:PSz/binary, Bin2/binary>> = Bin,
+ get_window([setelement(2, B0, Bin2) | Bs],
+ PSz, WSz-PSz,
+ [{DataType, Bin1}|Acc])
+ end;
+ WSz =< PSz -> %% use rest of window
+ <<Bin1:WSz/binary, Bin2/binary>> = Bin,
+ get_window([setelement(2, B0, Bin2) | Bs],
+ PSz, WSz-WSz,
+ [{DataType, Bin1}|Acc]);
+ true -> %% use packet size
+ <<Bin1:PSz/binary, Bin2/binary>> = Bin,
+ get_window([setelement(2, B0, Bin2) | Bs],
+ PSz, WSz-PSz,
+ [{DataType, Bin1}|Acc])
+ end;
+get_window([], _PSz, WSz, Acc) ->
+ {lists:reverse(Acc), WSz, []}.
+
+flow_control(Channel, Cache) ->
+ flow_control([window_adjusted], Channel, Cache).
+
+flow_control([], Channel, Cache) ->
+ ssh_channel:cache_update(Cache, Channel),
+ [];
+flow_control([_|_], #channel{flow_control = From} = Channel, Cache) ->
+ case From of
+ undefined ->
+ [];
+ _ ->
+ [{flow_control, Cache, Channel, From, ok}]
+ end.
+
+encode_pty_opts(Opts) ->
+ Bin = list_to_binary(encode_pty_opts2(Opts)),
+ Len = size(Bin),
+ <<?UINT32(Len), Bin/binary>>.
+
+encode_pty_opts2([]) ->
+ [?TTY_OP_END];
+encode_pty_opts2([{vintr,Value} | Opts]) ->
+ [?VINTR, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vquit,Value} | Opts]) ->
+ [?VQUIT, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{verase,Value} | Opts]) ->
+ [?VERASE, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vkill,Value} | Opts]) ->
+ [?VKILL, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{veof,Value} | Opts]) ->
+ [?VEOF, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{veol,Value} | Opts]) ->
+ [?VEOL, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{veol2,Value} | Opts]) ->
+ [?VEOL2, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vstart,Value} | Opts]) ->
+ [?VSTART, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vstop,Value} | Opts]) ->
+ [?VSTOP, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vsusp,Value} | Opts]) ->
+ [?VSUSP, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vdsusp,Value} | Opts]) ->
+ [?VDSUSP, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vreprint,Value} | Opts]) ->
+ [?VREPRINT, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vwerase,Value} | Opts]) ->
+ [ ?VWERASE, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vlnext,Value} | Opts]) ->
+ [?VLNEXT, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vflush,Value} | Opts]) ->
+ [?VFLUSH, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vswtch,Value} | Opts]) ->
+ [?VSWTCH, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vstatus,Value} | Opts]) ->
+ [?VSTATUS, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{vdiscard,Value} | Opts]) ->
+ [?VDISCARD, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{ignpar,Value} | Opts]) ->
+ [?IGNPAR, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{parmrk,Value} | Opts]) ->
+ [?PARMRK, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{inpck,Value} | Opts]) ->
+ [?INPCK, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{istrip,Value} | Opts]) ->
+ [?ISTRIP, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{inlcr,Value} | Opts]) ->
+ [?INLCR, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{igncr,Value} | Opts]) ->
+ [?IGNCR, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{icrnl,Value} | Opts]) ->
+ [?ICRNL, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{iuclc,Value} | Opts]) ->
+ [?IUCLC, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{ixon,Value} | Opts]) ->
+ [?IXON, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{ixany,Value} | Opts]) ->
+ [?IXANY, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{ixoff,Value} | Opts]) ->
+ [?IXOFF, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{imaxbel,Value} | Opts]) ->
+ [?IMAXBEL, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{isig,Value} | Opts]) ->
+ [?ISIG, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{icanon,Value} | Opts]) ->
+ [?ICANON, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{xcase,Value} | Opts]) ->
+ [?XCASE, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{echo,Value} | Opts]) ->
+ [?ECHO, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{echoe,Value} | Opts]) ->
+ [?ECHOE, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{echok,Value} | Opts]) ->
+ [?ECHOK, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{echonl,Value} | Opts]) ->
+ [?ECHONL, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{noflsh,Value} | Opts]) ->
+ [?NOFLSH, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{tostop,Value} | Opts]) ->
+ [?TOSTOP, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{iexten,Value} | Opts]) ->
+ [?IEXTEN, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{echoctl,Value} | Opts]) ->
+ [?ECHOCTL, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{echoke,Value} | Opts]) ->
+ [?ECHOKE, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{pendin,Value} | Opts]) ->
+ [?PENDIN, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{opost,Value} | Opts]) ->
+ [?OPOST, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{olcuc,Value} | Opts]) ->
+ [?OLCUC, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{onlcr,Value} | Opts]) ->
+ [?ONLCR, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{ocrnl,Value} | Opts]) ->
+ [?OCRNL, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{onocr,Value} | Opts]) ->
+ [?ONOCR, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{onlret,Value} | Opts]) ->
+ [?ONLRET, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{cs7,Value} | Opts]) ->
+ [?CS7, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{cs8,Value} | Opts]) ->
+ [?CS8, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{parenb,Value} | Opts]) ->
+ [?PARENB, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{parodd,Value} | Opts]) ->
+ [?PARODD, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{tty_op_ispeed,Value} | Opts]) ->
+ [?TTY_OP_ISPEED, ?uint32(Value) | encode_pty_opts2(Opts)];
+encode_pty_opts2([{tty_op_ospeed,Value} | Opts]) ->
+ [?TTY_OP_OSPEED, ?uint32(Value) | encode_pty_opts2(Opts)].
+
+decode_pty_opts(<<>>) ->
+ [];
+decode_pty_opts(<<0, 0, 0, 0>>) ->
+ [];
+decode_pty_opts(<<?UINT32(Len), Modes:Len/binary>>) ->
+ decode_pty_opts2(Modes);
+decode_pty_opts(Binary) ->
+ decode_pty_opts2(Binary).
+
+decode_pty_opts2(<<?TTY_OP_END>>) ->
+ [];
+decode_pty_opts2(<<Code, ?UINT32(Value), Tail/binary>>) ->
+ Op = case Code of
+ ?VINTR -> vintr;
+ ?VQUIT -> vquit;
+ ?VERASE -> verase;
+ ?VKILL -> vkill;
+ ?VEOF -> veof;
+ ?VEOL -> veol;
+ ?VEOL2 -> veol2;
+ ?VSTART -> vstart;
+ ?VSTOP -> vstop;
+ ?VSUSP -> vsusp;
+ ?VDSUSP -> vdsusp;
+ ?VREPRINT -> vreprint;
+ ?VWERASE -> vwerase;
+ ?VLNEXT -> vlnext;
+ ?VFLUSH -> vflush;
+ ?VSWTCH -> vswtch;
+ ?VSTATUS -> vstatus;
+ ?VDISCARD -> vdiscard;
+ ?IGNPAR -> ignpar;
+ ?PARMRK -> parmrk;
+ ?INPCK -> inpck;
+ ?ISTRIP -> istrip;
+ ?INLCR -> inlcr;
+ ?IGNCR -> igncr;
+ ?ICRNL -> icrnl;
+ ?IUCLC -> iuclc;
+ ?IXON -> ixon;
+ ?IXANY -> ixany;
+ ?IXOFF -> ixoff;
+ ?IMAXBEL -> imaxbel;
+ ?ISIG -> isig;
+ ?ICANON -> icanon;
+ ?XCASE -> xcase;
+ ?ECHO -> echo;
+ ?ECHOE -> echoe;
+ ?ECHOK -> echok;
+ ?ECHONL -> echonl;
+ ?NOFLSH -> noflsh;
+ ?TOSTOP -> tostop;
+ ?IEXTEN -> iexten;
+ ?ECHOCTL -> echoctl;
+ ?ECHOKE -> echoke;
+ ?PENDIN -> pendin;
+ ?OPOST -> opost;
+ ?OLCUC -> olcuc;
+ ?ONLCR -> onlcr;
+ ?OCRNL -> ocrnl;
+ ?ONOCR -> onocr;
+ ?ONLRET -> onlret;
+ ?CS7 -> cs7;
+ ?CS8 -> cs8;
+ ?PARENB -> parenb;
+ ?PARODD -> parodd;
+ ?TTY_OP_ISPEED -> tty_op_ispeed;
+ ?TTY_OP_OSPEED -> tty_op_ospeed;
+ _ -> Code
+ end,
+ [{Op, Value} | decode_pty_opts2(Tail)].
+
+decode_ip(Addr) when is_binary(Addr) ->
+ case inet_parse:address(binary_to_list(Addr)) of
+ {error,_} -> Addr;
+ {ok,A} -> A
+ end.
+
+%% This is really awful and that is why it is beeing phased out.
+handle_backwards_compatibility({_,_,_,_,_,_} = ChildSpec, _, _, _, _,
+ Address, Port, _) ->
+ SystemSup = ssh_system_sup:system_supervisor(Address, Port),
+ ChannelSup = ssh_system_sup:channel_supervisor(SystemSup),
+ ssh_channel_sup:start_child(ChannelSup, ChildSpec);
+
+handle_backwards_compatibility(Module, ConnectionManager, ChannelId,
+ RemoteChannelId, Opts,
+ _, _, Msg) when is_atom(Module) ->
+ {ok, SubSystemPid} = gen_server:start_link(Module, [Opts], []),
+ SubSystemPid !
+ {ssh_cm, ConnectionManager,
+ {open, ChannelId, RemoteChannelId, {session}}},
+ SubSystemPid ! Msg,
+ {ok, SubSystemPid};
+
+handle_backwards_compatibility(Fun, ConnectionManager, ChannelId,
+ RemoteChannelId,
+ _, _, _, Msg) when is_function(Fun) ->
+ SubSystemPid = Fun(),
+ SubSystemPid !
+ {ssh_cm, ConnectionManager,
+ {open, ChannelId, RemoteChannelId, {session}}},
+ SubSystemPid ! Msg,
+ {ok, SubSystemPid};
+
+handle_backwards_compatibility(ChildSpec,
+ ConnectionManager,
+ ChannelId, RemoteChannelId, _,
+ Address, Port, Msg) ->
+ SystemSup = ssh_system_sup:system_supervisor(Address, Port),
+ ChannelSup = ssh_system_sup:channel_supervisor(SystemSup),
+ {ok, SubSystemPid}
+ = ssh_channel_sup:start_child(ChannelSup, ChildSpec),
+ SubSystemPid !
+ {ssh_cm, ConnectionManager,
+ {open, ChannelId, RemoteChannelId, {session}}},
+ SubSystemPid ! Msg,
+ {ok, SubSystemPid}.
diff --git a/lib/ssh/src/ssh_connection_controler.erl b/lib/ssh/src/ssh_connection_controler.erl
new file mode 100644
index 0000000000..7960eb11c6
--- /dev/null
+++ b/lib/ssh/src/ssh_connection_controler.erl
@@ -0,0 +1,137 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%--------------------------------------------------------------------
+%% File : ssh_connection_controler.erl
+%% Description :
+%%
+%%--------------------------------------------------------------------
+
+-module(ssh_connection_controler).
+
+-behaviour(gen_server).
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([start_link/1, start_handler_child/2, start_manager_child/2,
+ connection_manager/1]).
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ code_change/3, terminate/2, stop/1]).
+
+-record(state, {role, manager, handler, timeout}).
+
+%%-----------------------------------------------------------------
+%% External interface functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: start/0
+%%-----------------------------------------------------------------
+start_link(Args) ->
+ gen_server:start_link(?MODULE, [Args], []).
+
+%% Will be called from the manager child process
+start_handler_child(ServerRef, Args) ->
+ gen_server:call(ServerRef, {handler, self(), Args}, infinity).
+
+%% Will be called from the acceptor process
+start_manager_child(ServerRef, Args) ->
+ gen_server:call(ServerRef, {manager, Args}, infinity).
+
+connection_manager(ServerRef) ->
+ {ok, gen_server:call(ServerRef, manager, infinity)}.
+
+%%-----------------------------------------------------------------
+%% Internal interface functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: stop/1
+%%-----------------------------------------------------------------
+stop(Pid) ->
+ gen_server:cast(Pid, stop).
+
+%%-----------------------------------------------------------------
+%% Server functions
+%%-----------------------------------------------------------------
+%%-----------------------------------------------------------------
+%% Func: init/1
+%%-----------------------------------------------------------------
+init([Opts]) ->
+ process_flag(trap_exit, true),
+ case proplists:get_value(role, Opts) of
+ client ->
+ {ok, Manager} = ssh_connection_manager:start_link([client, Opts]),
+ {ok, #state{role = client, manager = Manager}};
+ _server ->
+ %% Children started by acceptor process
+ {ok, #state{role = server}}
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: terminate/2
+%%-----------------------------------------------------------------
+terminate(_Reason, #state{}) ->
+ ok.
+
+%%-----------------------------------------------------------------
+%% Func: handle_call/3
+%%-----------------------------------------------------------------
+handle_call({handler, Pid, [Role, Socket, Opts]}, _From, State) ->
+ {ok, Handler} = ssh_connection_handler:start_link(Role, Pid, Socket, Opts),
+ {reply, {ok, Handler}, State#state{handler = Handler}};
+handle_call({manager, [server = Role, Socket, Opts]}, _From, State) ->
+ {ok, Manager} = ssh_connection_manager:start_link([Role, Socket, Opts]),
+ {reply, {ok, Manager}, State#state{manager = Manager}};
+handle_call({manager, [client = Role | Opts]}, _From, State) ->
+ {ok, Manager} = ssh_connection_manager:start_link([Role, Opts]),
+ {reply, {ok, Manager}, State#state{manager = Manager}};
+handle_call(manager, _From, State) ->
+ {reply, State#state.manager, State};
+handle_call(stop, _From, State) ->
+ {stop, normal, ok, State};
+handle_call(_, _, State) ->
+ {noreply, State, State#state.timeout}.
+
+%%-----------------------------------------------------------------
+%% Func: handle_cast/2
+%%-----------------------------------------------------------------
+handle_cast(stop, State) ->
+ {stop, normal, State};
+handle_cast(_, State) ->
+ {noreply, State, State#state.timeout}.
+
+%%-----------------------------------------------------------------
+%% Func: handle_info/2
+%%-----------------------------------------------------------------
+%% handle_info(ssh_connected, State) ->
+%% {stop, normal, State};
+%% Servant termination.
+handle_info({'EXIT', _Pid, normal}, State) ->
+ {stop, normal, State}.
+
+%%-----------------------------------------------------------------
+%% Func: code_change/3
+%%-----------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
new file mode 100644
index 0000000000..5240b4b4c5
--- /dev/null
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -0,0 +1,879 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Handles the setup of an ssh connection, e.i. both the
+%% setup SSH Transport Layer Protocol (RFC 4253) and Authentication
+%% Protocol (RFC 4252). Details of the different protocols are
+%% implemented in ssh_transport.erl, ssh_auth.erl
+%% ----------------------------------------------------------------------
+
+-module(ssh_connection_handler).
+
+-behaviour(gen_fsm).
+
+-include("ssh.hrl").
+-include("ssh_transport.hrl").
+-include("ssh_auth.hrl").
+-include("ssh_connect.hrl").
+
+-export([start_link/4, send/2, renegotiate/1, send_event/2,
+ connection_info/3,
+ peer_address/1]).
+
+%% gen_fsm callbacks
+-export([hello/2, kexinit/2, key_exchange/2, new_keys/2,
+ userauth/2, connected/2]).
+
+-export([init/1, state_name/3, handle_event/3,
+ handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
+
+%% spawn export
+-export([ssh_info_handler/3]).
+
+-record(state, {
+ transport_protocol, % ex: tcp
+ transport_cb,
+ transport_close_tag,
+ ssh_params, % #ssh{} - from ssh.hrl
+ socket, % socket()
+ decoded_data_buffer, % binary()
+ encoded_data_buffer, % binary()
+ undecoded_packet_length, % integer()
+ key_exchange_init_msg, % #ssh_msg_kexinit{}
+ renegotiate = false, % boolean()
+ manager, % pid()
+ connection_queue,
+ address,
+ port,
+ opts
+ }).
+
+-define(DBG_MESSAGE, true).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> ok,Pid} | ignore | {error,Error}
+%% Description:Creates a gen_fsm process which calls Module:init/1 to
+%% initialize. To ensure a synchronized start-up procedure, this function
+%% does not return until Module:init/1 has returned.
+%%--------------------------------------------------------------------
+start_link(Role, Manager, Socket, Options) ->
+ gen_fsm:start_link(?MODULE, [Role, Manager, Socket, Options], []).
+
+send(ConnectionHandler, Data) ->
+ send_all_state_event(ConnectionHandler, {send, Data}).
+
+renegotiate(ConnectionHandler) ->
+ send_all_state_event(ConnectionHandler, renegotiate).
+
+connection_info(ConnectionHandler, From, Options) ->
+ send_all_state_event(ConnectionHandler, {info, From, Options}).
+
+%% Replaced with option to connection_info/3. For now keep
+%% for backwards compatibility
+peer_address(ConnectionHandler) ->
+ sync_send_all_state_event(ConnectionHandler, peer_address).
+
+%%====================================================================
+%% gen_fsm callbacks
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, StateName, State} |
+%% {ok, StateName, State, Timeout} |
+%% ignore |
+%% {stop, StopReason}
+%% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
+%% gen_fsm:start_link/3,4, this function is called by the new process to
+%% initialize.
+%%--------------------------------------------------------------------
+init([Role, Manager, Socket, SshOpts]) ->
+ {A,B,C} = erlang:now(),
+ random:seed(A, B, C),
+ {NumVsn, StrVsn} = ssh_transport:versions(Role, SshOpts),
+ ssh_bits:install_messages(ssh_transport:transport_messages(NumVsn)),
+ {Protocol, Callback, CloseTag} =
+ proplists:get_value(transport, SshOpts, {tcp, gen_tcp, tcp_closed}),
+ Ssh = init_ssh(Role, NumVsn, StrVsn, SshOpts, Socket),
+ {ok, hello, #state{ssh_params =
+ Ssh#ssh{send_sequence = 0, recv_sequence = 0},
+ socket = Socket,
+ decoded_data_buffer = <<>>,
+ encoded_data_buffer = <<>>,
+ transport_protocol = Protocol,
+ transport_cb = Callback,
+ transport_close_tag = CloseTag,
+ manager = Manager,
+ opts = SshOpts
+ }}.
+%%--------------------------------------------------------------------
+%% Function:
+%% state_name(Event, State) -> {next_state, NextStateName, NextState}|
+%% {next_state, NextStateName,
+%% NextState, Timeout} |
+%% {stop, Reason, NewState}
+%% Description:There should be one instance of this function for each possible
+%% state name. Whenever a gen_fsm receives an event sent using
+%% gen_fsm:send_event/2, the instance of this function with the same name as
+%% the current state name StateName is called to handle the event. It is also
+%% called if a timeout occurs.
+%%--------------------------------------------------------------------
+hello(socket_control, #state{socket = Socket, ssh_params = Ssh} = State) ->
+ VsnMsg = ssh_transport:hello_version_msg(string_version(Ssh)),
+ send_msg(VsnMsg, State),
+ inet:setopts(Socket, [{packet, line}]),
+ {next_state, hello, next_packet(State)};
+
+hello({info_line, _Line}, State) ->
+ {next_state, hello, next_packet(State)};
+
+hello({version_exchange, Version}, #state{ssh_params = Ssh0,
+ socket = Socket} = State) ->
+ {NumVsn, StrVsn} = ssh_transport:handle_hello_version(Version),
+ case handle_version(NumVsn, StrVsn, Ssh0) of
+ {ok, Ssh1} ->
+ inet:setopts(Socket, [{packet,0}, {mode,binary}]),
+ {KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(Ssh1),
+ send_msg(SshPacket, State),
+ {next_state, kexinit, next_packet(State#state{ssh_params = Ssh,
+ key_exchange_init_msg =
+ KeyInitMsg})};
+ not_supported ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code =
+ ?SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,
+ description = "Protocol version " ++ StrVsn
+ ++ " not supported",
+ language = "en"},
+ handle_disconnect(DisconnectMsg, State)
+ end.
+
+kexinit({#ssh_msg_kexinit{} = Kex, Payload},
+ #state{ssh_params = #ssh{role = Role} = Ssh0,
+ key_exchange_init_msg = OwnKex} =
+ State) ->
+ Ssh1 = ssh_transport:key_init(opposite_role(Role), Ssh0, Payload),
+ try ssh_transport:handle_kexinit_msg(Kex, OwnKex, Ssh1) of
+ {ok, NextKexMsg, Ssh} when Role == client ->
+ send_msg(NextKexMsg, State),
+ {next_state, key_exchange,
+ next_packet(State#state{ssh_params = Ssh})};
+ {ok, Ssh} when Role == server ->
+ {next_state, key_exchange,
+ next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end.
+
+key_exchange(#ssh_msg_kexdh_init{} = Msg,
+ #state{ssh_params = #ssh{role = server} =Ssh0} = State) ->
+ try ssh_transport:handle_kexdh_init(Msg, Ssh0) of
+ {ok, KexdhReply, Ssh1} ->
+ send_msg(KexdhReply, State),
+ {ok, NewKeys, Ssh} = ssh_transport:new_keys_message(Ssh1),
+ send_msg(NewKeys, State),
+ {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+key_exchange(#ssh_msg_kexdh_reply{} = Msg,
+ #state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
+ try ssh_transport:handle_kexdh_reply(Msg, Ssh0) of
+ {ok, NewKeys, Ssh} ->
+ send_msg(NewKeys, State),
+ {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+key_exchange(#ssh_msg_kex_dh_gex_group{} = Msg,
+ #state{ssh_params = #ssh{role = server} = Ssh0} = State) ->
+ try ssh_transport:handle_kex_dh_gex_group(Msg, Ssh0) of
+ {ok, NextKexMsg, Ssh1} ->
+ send_msg(NextKexMsg, State),
+ {ok, NewKeys, Ssh} = ssh_transport:new_keys_message(Ssh1),
+ send_msg(NewKeys, State),
+ {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+key_exchange(#ssh_msg_kex_dh_gex_request{} = Msg,
+ #state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
+ try ssh_transport:handle_kex_dh_gex_request(Msg, Ssh0) of
+ {ok, NextKexMsg, Ssh} ->
+ send_msg(NextKexMsg, State),
+ {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+key_exchange(#ssh_msg_kex_dh_gex_reply{} = Msg,
+ #state{ssh_params = #ssh{role = client} = Ssh0} = State) ->
+ try ssh_transport:handle_kex_dh_gex_reply(Msg, Ssh0) of
+ {ok, NewKeys, Ssh} ->
+ send_msg(NewKeys, State),
+ {next_state, new_keys, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end.
+
+new_keys(#ssh_msg_newkeys{} = Msg, #state{ssh_params = Ssh0} = State0) ->
+ try ssh_transport:handle_new_keys(Msg, Ssh0) of
+ {ok, Ssh} ->
+ {NextStateName, State} =
+ after_new_keys(State0#state{ssh_params = Ssh}),
+ {next_state, NextStateName, next_packet(State)}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State0),
+ {stop, normal, State0}
+ end.
+
+userauth(#ssh_msg_service_request{name = "ssh-userauth"} = Msg,
+ #state{ssh_params = #ssh{role = server,
+ session_id = SessionId} = Ssh0} = State) ->
+ ssh_bits:install_messages(ssh_auth:userauth_messages()),
+ try ssh_auth:handle_userauth_request(Msg, SessionId, Ssh0) of
+ {ok, {Reply, Ssh}} ->
+ send_msg(Reply, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+userauth(#ssh_msg_service_accept{name = "ssh-userauth"},
+ #state{ssh_params = #ssh{role = client,
+ service = "ssh-userauth"} = Ssh0} =
+ State) ->
+ {Msg, Ssh} = ssh_auth:init_userauth_request_msg(Ssh0),
+ send_msg(Msg, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})};
+
+userauth(#ssh_msg_userauth_request{service = "ssh-connection",
+ method = "none"} = Msg,
+ #state{ssh_params = #ssh{session_id = SessionId, role = server,
+ service = "ssh-connection"} = Ssh0
+ } = State) ->
+ try ssh_auth:handle_userauth_request(Msg, SessionId, Ssh0) of
+ {not_authorized, {_User, _Reason}, {Reply, Ssh}} ->
+ send_msg(Reply, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+userauth(#ssh_msg_userauth_request{service = "ssh-connection",
+ method = Method} = Msg,
+ #state{ssh_params = #ssh{session_id = SessionId, role = server,
+ service = "ssh-connection",
+ peer = {_, Address}} = Ssh0,
+ opts = Opts, manager = Pid} = State) ->
+ try ssh_auth:handle_userauth_request(Msg, SessionId, Ssh0) of
+ {authorized, User, {Reply, Ssh}} ->
+ send_msg(Reply, State),
+ ssh_userreg:register_user(User, Pid),
+ Pid ! ssh_connected,
+ connected_fun(User, Address, Method, Opts),
+ {next_state, connected,
+ next_packet(State#state{ssh_params = Ssh})};
+ {not_authorized, {User, Reason}, {Reply, Ssh}} ->
+ retry_fun(User, Reason, Opts),
+ send_msg(Reply, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+userauth(#ssh_msg_userauth_info_request{} = Msg,
+ #state{ssh_params = #ssh{role = client,
+ io_cb = IoCb} = Ssh0} = State) ->
+ try ssh_auth:handle_userauth_info_request(Msg, IoCb, Ssh0) of
+ {ok, {Reply, Ssh}} ->
+ send_msg(Reply, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+userauth(#ssh_msg_userauth_info_response{} = Msg,
+ #state{ssh_params = #ssh{role = server} = Ssh0} = State) ->
+ try ssh_auth:handle_userauth_info_response(Msg, Ssh0) of
+ {ok, {Reply, Ssh}} ->
+ send_msg(Reply, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
+ catch
+ #ssh_msg_disconnect{} = DisconnectMsg ->
+ handle_disconnect(DisconnectMsg, State)
+ end;
+
+userauth(#ssh_msg_userauth_success{}, #state{ssh_params = #ssh{role = client},
+ manager = Pid} = State) ->
+ Pid ! ssh_connected,
+ {next_state, connected, next_packet(State)};
+
+userauth(#ssh_msg_userauth_failure{},
+ #state{ssh_params = #ssh{role = client,
+ userauth_methods = []}}
+ = State) ->
+ Msg = #ssh_msg_disconnect{code =
+ ?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
+ description = "Unable to connect using the available"
+ " authentication methods",
+ language = "en"},
+ handle_disconnect(Msg, State);
+
+%% Server tells us which authentication methods that are allowed
+userauth(#ssh_msg_userauth_failure{authentications = Methodes},
+ #state{ssh_params = #ssh{role = client,
+ userauth_methods = none} = Ssh0} = State) ->
+ AuthMethods = string:tokens(Methodes, ","),
+ {Msg, Ssh} = ssh_auth:userauth_request_msg(
+ Ssh0#ssh{userauth_methods = AuthMethods}),
+ send_msg(Msg, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})};
+
+%% The prefered authentication method failed try next method
+userauth(#ssh_msg_userauth_failure{},
+ #state{ssh_params = #ssh{role = client} = Ssh0,
+ manager = Pid} = State) ->
+ case ssh_auth:userauth_request_msg(Ssh0) of
+ {disconnect, Event, {Msg, _}} ->
+ try
+ send_msg(Msg, State),
+ ssh_connection_manager:event(Pid, Event)
+ catch
+ exit:{noproc, _Reason} ->
+ Report = io_lib:format("Connection Manager terminated: ~p~n",
+ [Pid]),
+ error_logger:info_report(Report);
+ exit:Exit ->
+ Report = io_lib:format("Connection Manager returned:~n~p~n~p~n",
+ [Msg, Exit]),
+ error_logger:info_report(Report)
+ end,
+ {stop, normal, State};
+ {Msg, Ssh} ->
+ send_msg(Msg, State),
+ {next_state, userauth, next_packet(State#state{ssh_params = Ssh})}
+ end;
+
+userauth(#ssh_msg_userauth_banner{},
+ #state{ssh_params = #ssh{userauth_quiet_mode = true,
+ role = client}} = State) ->
+ {next_state, userauth, next_packet(State)};
+userauth(#ssh_msg_userauth_banner{message = Msg},
+ #state{ssh_params =
+ #ssh{userauth_quiet_mode = false, role = client}} = State) ->
+ io:format("~s", [Msg]),
+ {next_state, userauth, next_packet(State)}.
+
+connected({#ssh_msg_kexinit{}, _Payload} = Event, State) ->
+ kexinit(Event, State#state{renegotiate = true}).
+
+%%--------------------------------------------------------------------
+%% Function:
+%% state_name(Event, From, State) -> {next_state, NextStateName, NextState} |
+%% {next_state, NextStateName,
+%% NextState, Timeout} |
+%% {reply, Reply, NextStateName, NextState}|
+%% {reply, Reply, NextStateName,
+%% NextState, Timeout} |
+%% {stop, Reason, NewState}|
+%% {stop, Reason, Reply, NewState}
+%% Description: There should be one instance of this function for each
+%% possible state name. Whenever a gen_fsm receives an event sent using
+%% gen_fsm:sync_send_event/2,3, the instance of this function with the same
+%% name as the current state name StateName is called to handle the event.
+%%--------------------------------------------------------------------
+state_name(_Event, _From, State) ->
+ Reply = ok,
+ {reply, Reply, state_name, State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_event(Event, StateName, State) -> {next_state, NextStateName,
+%% NextState} |
+%% {next_state, NextStateName,
+%% NextState, Timeout} |
+%% {stop, Reason, NewState}
+%% Description: Whenever a gen_fsm receives an event sent using
+%% gen_fsm:send_all_state_event/2, this function is called to handle
+%% the event.
+%%--------------------------------------------------------------------
+handle_event({send, Data}, StateName, #state{ssh_params = Ssh0} = State) ->
+ {Packet, Ssh} = ssh_transport:pack(Data, Ssh0),
+ send_msg(Packet, State),
+ {next_state, StateName, next_packet(State#state{ssh_params = Ssh})};
+
+handle_event(#ssh_msg_disconnect{} = Msg, _StateName,
+ #state{manager = Pid} = State) ->
+ (catch ssh_connection_manager:event(Pid, Msg)),
+ {stop, normal, State};
+
+handle_event(#ssh_msg_ignore{}, StateName, State) ->
+ {next_state, StateName, next_packet(State)};
+
+handle_event(#ssh_msg_debug{always_display = true, message = DbgMsg},
+ StateName, State) ->
+ io:format("DEBUG: ~p\n", [DbgMsg]),
+ {next_state, StateName, next_packet(State)};
+
+handle_event(#ssh_msg_debug{}, StateName, State) ->
+ {next_state, StateName, next_packet(State)};
+
+handle_event(#ssh_msg_unimplemented{}, StateName, State) ->
+ {next_state, StateName, next_packet(State)};
+
+handle_event(renegotiate, connected, #state{ssh_params = Ssh0}
+ = State) ->
+ {KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(Ssh0),
+ send_msg(SshPacket, State),
+ {next_state, connected,
+ next_packet(State#state{ssh_params = Ssh,
+ key_exchange_init_msg = KeyInitMsg,
+ renegotiate = true})};
+
+handle_event(renegotiate, StateName, State) ->
+ %% Allready in keyexcahange so ignore
+ {next_state, StateName, State};
+
+handle_event({info, From, Options}, StateName, #state{ssh_params = Ssh} = State) ->
+ spawn(?MODULE, ssh_info_handler, [Options, Ssh, From]),
+ {next_state, StateName, State};
+
+handle_event({unknown, Data}, StateName, State) ->
+ Msg = #ssh_msg_unimplemented{sequence = Data},
+ send_msg(Msg, State),
+ {next_state, StateName, next_packet(State)}.
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_sync_event(Event, From, StateName,
+%% State) -> {next_state, NextStateName, NextState} |
+%% {next_state, NextStateName, NextState,
+%% Timeout} |
+%% {reply, Reply, NextStateName, NextState}|
+%% {reply, Reply, NextStateName, NextState,
+%% Timeout} |
+%% {stop, Reason, NewState} |
+%% {stop, Reason, Reply, NewState}
+%% Description: Whenever a gen_fsm receives an event sent using
+%% gen_fsm:sync_send_all_state_event/2,3, this function is called to handle
+%% the event.
+%%--------------------------------------------------------------------
+
+%% Replaced with option to connection_info/3. For now keep
+%% for backwards compatibility
+handle_sync_event(peer_address, _From, StateName,
+ #state{ssh_params = #ssh{peer = {_, Address}}} = State) ->
+ {reply, {ok, Address}, StateName, State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_info(Info,StateName,State)-> {next_state, NextStateName, NextState}|
+%% {next_state, NextStateName, NextState,
+%% Timeout} |
+%% {stop, Reason, NewState}
+%% Description: This function is called by a gen_fsm when it receives any
+%% other message than a synchronous or asynchronous event
+%% (or a system message).
+%%--------------------------------------------------------------------
+handle_info({Protocol, Socket, "SSH-" ++ _ = Version}, hello,
+ #state{socket = Socket,
+ transport_protocol = Protocol} = State ) ->
+ event({version_exchange, Version}, hello, State);
+
+handle_info({Protocol, Socket, Info}, hello,
+ #state{socket = Socket,
+ transport_protocol = Protocol} = State) ->
+ event({info_line, Info}, hello, State);
+
+handle_info({Protocol, Socket, Data}, Statename,
+ #state{socket = Socket,
+ transport_protocol = Protocol,
+ ssh_params = #ssh{decrypt_block_size = BlockSize,
+ recv_mac_size = MacSize} = Ssh0,
+ decoded_data_buffer = <<>>,
+ encoded_data_buffer = EncData0} = State0) ->
+
+ %% Implementations SHOULD decrypt the length after receiving the
+ %% first 8 (or cipher block size, whichever is larger) bytes of a
+ %% packet. (RFC 4253: Section 6 - Binary Packet Protocol)
+ case size(EncData0) + size(Data) >= max(8, BlockSize) of
+ true ->
+ {Ssh, SshPacketLen, DecData, EncData} =
+ ssh_transport:decrypt_first_block(<<EncData0/binary,
+ Data/binary>>, Ssh0),
+ case SshPacketLen > ?SSH_MAX_PACKET_SIZE of
+ true ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code =
+ ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Bad packet length "
+ ++ integer_to_list(SshPacketLen),
+ language = "en"},
+ handle_disconnect(DisconnectMsg, State0);
+ false ->
+ RemainingSshPacketLen =
+ (SshPacketLen + ?SSH_LENGHT_INDICATOR_SIZE) -
+ BlockSize + MacSize,
+ State = State0#state{ssh_params = Ssh},
+ handle_ssh_packet_data(RemainingSshPacketLen,
+ DecData, EncData, Statename,
+ State)
+ end;
+ false ->
+ {next_state, Statename,
+ next_packet(State0#state{encoded_data_buffer =
+ <<EncData0/binary, Data/binary>>})}
+ end;
+
+handle_info({Protocol, Socket, Data}, Statename,
+ #state{socket = Socket,
+ transport_protocol = Protocol,
+ decoded_data_buffer = DecData,
+ encoded_data_buffer = EncData,
+ undecoded_packet_length = Len} =
+ State) when is_integer(Len) ->
+ handle_ssh_packet_data(Len, DecData, <<EncData/binary, Data/binary>>,
+ Statename, State);
+
+handle_info({CloseTag, _Socket}, _StateName,
+ #state{transport_close_tag = CloseTag, %%manager = Pid,
+ ssh_params = #ssh{role = _Role, opts = _Opts}} = State) ->
+ %%ok = ssh_connection_manager:delivered(Pid),
+ {stop, normal, State}.
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, StateName, State) -> void()
+%% Description:This function is called by a gen_fsm when it is about
+%% to terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_fsm terminates with
+%% Reason. The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(normal, _, #state{transport_cb = Transport,
+ socket = Socket}) ->
+ (catch Transport:close(Socket)),
+ ok;
+
+terminate(shutdown, _, State) ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "Application disconnect",
+ language = "en"},
+ handle_disconnect(DisconnectMsg, State);
+
+terminate(Reason, _, State) ->
+ Desc = io_lib:format("Erlang ssh connection handler failed with reason: "
+ "~p , please report this to [email protected] \n",
+ [Reason]),
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_CONNECTION_LOST,
+ description = Desc,
+ language = "en"},
+ handle_disconnect(DisconnectMsg, State).
+
+%%--------------------------------------------------------------------
+%% Function:
+%% code_change(OldVsn, StateName, State, Extra) -> {ok, StateName, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, StateName, State, _Extra) ->
+ {ok, StateName, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+init_ssh(client = Role, Vsn, Version, Options, Socket) ->
+ IOCb = case proplists:get_value(user_interaction, Options, true) of
+ true ->
+ ssh_io;
+ false ->
+ ssh_no_io
+ end,
+
+ AuthMethods = proplists:get_value(auth_methods, Options,
+ ?SUPPORTED_AUTH_METHODS),
+ {ok, PeerAddr} = inet:peername(Socket),
+
+ PeerName = proplists:get_value(host, Options),
+
+ #ssh{role = Role,
+ c_vsn = Vsn,
+ c_version = Version,
+ key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ io_cb = IOCb,
+ userauth_quiet_mode = proplists:get_value(quiet_mode, Options, false),
+ opts = Options,
+ userauth_supported_methods = AuthMethods,
+ peer = {PeerName, PeerAddr}
+ };
+
+init_ssh(server = Role, Vsn, Version, Options, Socket) ->
+
+ AuthMethods = proplists:get_value(auth_methods, Options,
+ ?SUPPORTED_AUTH_METHODS),
+ {ok, PeerAddr} = inet:peername(Socket),
+
+ #ssh{role = Role,
+ s_vsn = Vsn,
+ s_version = Version,
+ key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ io_cb = proplists:get_value(io_cb, Options, ssh_io),
+ opts = Options,
+ userauth_supported_methods = AuthMethods,
+ peer = {undefined, PeerAddr}
+ }.
+
+send_msg(Msg, #state{socket = Socket, transport_cb = Transport}) ->
+ Transport:send(Socket, Msg).
+
+handle_version({2, 0} = NumVsn, StrVsn, Ssh0) ->
+ Ssh = counterpart_versions(NumVsn, StrVsn, Ssh0),
+ {ok, Ssh};
+handle_version(_,_,_) ->
+ not_supported.
+
+string_version(#ssh{role = client, c_version = Vsn}) ->
+ Vsn;
+string_version(#ssh{role = server, s_version = Vsn}) ->
+ Vsn.
+
+send_event(FsmPid, Event) ->
+ gen_fsm:send_event(FsmPid, Event).
+
+send_all_state_event(FsmPid, Event) ->
+ gen_fsm:send_all_state_event(FsmPid, Event).
+
+sync_send_all_state_event(FsmPid, Event) ->
+ gen_fsm:sync_send_all_state_event(FsmPid, Event).
+
+%% simulate send_all_state_event(self(), Event)
+event(#ssh_msg_disconnect{} = Event, StateName, State) ->
+ handle_event(Event, StateName, State);
+event(#ssh_msg_ignore{} = Event, StateName, State) ->
+ handle_event(Event, StateName, State);
+event(#ssh_msg_debug{} = Event, StateName, State) ->
+ handle_event(Event, StateName, State);
+event(#ssh_msg_unimplemented{} = Event, StateName, State) ->
+ handle_event(Event, StateName, State);
+%% simulate send_event(self(), Event)
+event(Event, StateName, State) ->
+ ?MODULE:StateName(Event, State).
+
+generate_event(<<?BYTE(Byte), _/binary>> = Msg, StateName,
+ #state{manager = Pid} = State0, EncData)
+ when Byte == ?SSH_MSG_GLOBAL_REQUEST;
+ Byte == ?SSH_MSG_REQUEST_SUCCESS;
+ Byte == ?SSH_MSG_REQUEST_FAILURE;
+ Byte == ?SSH_MSG_CHANNEL_OPEN;
+ Byte == ?SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
+ Byte == ?SSH_MSG_CHANNEL_OPEN_FAILURE;
+ Byte == ?SSH_MSG_CHANNEL_WINDOW_ADJUST;
+ Byte == ?SSH_MSG_CHANNEL_DATA;
+ Byte == ?SSH_MSG_CHANNEL_EXTENDED_DATA;
+ Byte == ?SSH_MSG_CHANNEL_EOF;
+ Byte == ?SSH_MSG_CHANNEL_CLOSE;
+ Byte == ?SSH_MSG_CHANNEL_REQUEST;
+ Byte == ?SSH_MSG_CHANNEL_SUCCESS;
+ Byte == ?SSH_MSG_CHANNEL_FAILURE ->
+ ssh_connection_manager:event(Pid, Msg),
+ State = generate_event_new_state(State0, EncData),
+ next_packet(State),
+ {next_state, StateName, State};
+
+generate_event(Msg, StateName, State0, EncData) ->
+ Event = ssh_bits:decode(Msg),
+ State = generate_event_new_state(State0, EncData),
+ case Event of
+ #ssh_msg_kexinit{} ->
+ %% We need payload for verification later.
+ event({Event, Msg}, StateName, State);
+ _ ->
+ event(Event, StateName, State)
+ end.
+
+generate_event_new_state(#state{ssh_params =
+ #ssh{recv_sequence = SeqNum0}
+ = Ssh} = State, EncData) ->
+ SeqNum = ssh_transport:next_seqnum(SeqNum0),
+ State#state{ssh_params = Ssh#ssh{recv_sequence = SeqNum},
+ decoded_data_buffer = <<>>,
+ encoded_data_buffer = EncData,
+ undecoded_packet_length = undefined}.
+
+
+next_packet(#state{decoded_data_buffer = <<>>,
+ encoded_data_buffer = Buff,
+ socket = Socket,
+ transport_protocol = Protocol} =
+ State) when Buff =/= <<>> andalso size(Buff) >= 8 ->
+ %% More data from the next packet has been received
+ %% Fake a socket-recive message so that the data will be processed
+ self() ! {Protocol, Socket, <<>>} ,
+ State;
+
+next_packet(#state{socket = Socket} = State) ->
+ inet:setopts(Socket, [{active, once}]),
+ State.
+
+after_new_keys(#state{renegotiate = true} = State) ->
+ {connected, State#state{renegotiate = false}};
+after_new_keys(#state{renegotiate = false,
+ ssh_params = #ssh{role = client} = Ssh0} = State) ->
+ ssh_bits:install_messages(ssh_auth:userauth_messages()),
+ {Msg, Ssh} = ssh_auth:service_request_msg(Ssh0),
+ send_msg(Msg, State),
+ {userauth, State#state{ssh_params = Ssh}};
+after_new_keys(#state{renegotiate = false,
+ ssh_params = #ssh{role = server}} = State) ->
+ {userauth, State}.
+
+max(N, M) when N > M ->
+ N;
+max(_, M) ->
+ M.
+
+handle_ssh_packet_data(RemainingSshPacketLen, DecData, EncData, StateName,
+ State) ->
+ EncSize = size(EncData),
+ case RemainingSshPacketLen > EncSize of
+ true ->
+ {next_state, StateName,
+ next_packet(State#state{decoded_data_buffer = DecData,
+ encoded_data_buffer = EncData,
+ undecoded_packet_length =
+ RemainingSshPacketLen})};
+ false ->
+ handle_ssh_packet(RemainingSshPacketLen, StateName,
+ State#state{decoded_data_buffer = DecData,
+ encoded_data_buffer = EncData})
+
+ end.
+
+handle_ssh_packet(Length, StateName, #state{decoded_data_buffer = DecData0,
+ encoded_data_buffer = EncData0,
+ ssh_params = Ssh0,
+ transport_protocol = _Protocol,
+ socket = _Socket} = State0) ->
+ {Ssh1, DecData, EncData, Mac} =
+ ssh_transport:unpack(EncData0, Length, Ssh0),
+ SshPacket = <<DecData0/binary, DecData/binary>>,
+ case ssh_transport:is_valid_mac(Mac, SshPacket, Ssh1) of
+ true ->
+ PacketData = ssh_transport:msg_data(SshPacket),
+ {Ssh1, Msg} = ssh_transport:decompress(Ssh1, PacketData),
+ generate_event(Msg, StateName,
+ State0#state{ssh_params = Ssh1,
+ %% Important to be set for
+ %% next_packet
+ decoded_data_buffer = <<>>}, EncData);
+ false ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Bad mac",
+ language = "en"},
+ handle_disconnect(DisconnectMsg, State0)
+ end.
+
+handle_disconnect(#ssh_msg_disconnect{} = Msg,
+ #state{ssh_params = Ssh0, manager = Pid} = State) ->
+ {SshPacket, Ssh} = ssh_transport:ssh_packet(Msg, Ssh0),
+ try
+ send_msg(SshPacket, State),
+ ssh_connection_manager:event(Pid, Msg)
+ catch
+ exit:{noproc, _Reason} ->
+ Report = io_lib:format("~p Connection Manager terminated: ~p~n",
+ [self(), Pid]),
+ error_logger:info_report(Report);
+ exit:Exit ->
+ Report = io_lib:format("Connection Manager returned:~n~p~n~p~n",
+ [Msg, Exit]),
+ error_logger:info_report(Report)
+ end,
+ {stop, normal, State#state{ssh_params = Ssh}}.
+
+counterpart_versions(NumVsn, StrVsn, #ssh{role = server} = Ssh) ->
+ Ssh#ssh{c_vsn = NumVsn , c_version = StrVsn};
+counterpart_versions(NumVsn, StrVsn, #ssh{role = client} = Ssh) ->
+ Ssh#ssh{s_vsn = NumVsn , s_version = StrVsn}.
+
+opposite_role(client) ->
+ server;
+opposite_role(server) ->
+ client.
+connected_fun(User, PeerAddr, Method, Opts) ->
+ case proplists:get_value(connectfun, Opts) of
+ undefined ->
+ ok;
+ Fun ->
+ catch Fun(User, PeerAddr, Method)
+ end.
+
+retry_fun(_, undefined, _) ->
+ ok;
+
+retry_fun(User, {error, Reason}, Opts) ->
+ case proplists:get_value(failfun, Opts) of
+ undefined ->
+ ok;
+ Fun ->
+ catch Fun(User, Reason)
+ end;
+
+retry_fun(User, Reason, Opts) ->
+ case proplists:get_value(infofun, Opts) of
+ undefined ->
+ ok;
+ Fun ->
+ catch Fun(User, Reason)
+ end.
+
+ssh_info_handler(Options, Ssh, From) ->
+ Info = ssh_info(Options, Ssh, []),
+ ssh_connection_manager:send_msg({channel_requst_reply, From, Info}).
+
+ssh_info([], _, Acc) ->
+ Acc;
+
+ssh_info([client_version | Rest], #ssh{c_vsn = IntVsn,
+ c_version = StringVsn} = SshParams, Acc) ->
+ ssh_info(Rest, SshParams, [{client_version, {IntVsn, StringVsn}} | Acc]);
+
+ssh_info([server_version | Rest], #ssh{s_vsn = IntVsn,
+ s_version = StringVsn} = SshParams, Acc) ->
+ ssh_info(Rest, SshParams, [{server_version, {IntVsn, StringVsn}} | Acc]);
+
+ssh_info([peer | Rest], #ssh{peer = Peer} = SshParams, Acc) ->
+ ssh_info(Rest, SshParams, [{peer, Peer} | Acc]);
+
+ssh_info([ _ | Rest], SshParams, Acc) ->
+ ssh_info(Rest, SshParams, Acc).
diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl
new file mode 100644
index 0000000000..3863005e74
--- /dev/null
+++ b/lib/ssh/src/ssh_connection_manager.erl
@@ -0,0 +1,760 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Handles multiplexing to ssh channels and global connection
+%% requests e.i. the SSH Connection Protocol (RFC 4254), that provides
+%% interactive login sessions, remote execution of commands, forwarded
+%% TCP/IP connections, and forwarded X11 connections. Details of the
+%% protocol is implemented in ssh_connection.erl
+%% ----------------------------------------------------------------------
+-module(ssh_connection_manager).
+
+-behaviour(gen_server).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+-include("ssh_transport.hrl").
+
+-export([start_link/1]).
+
+-export([info/1, info/2,
+ renegotiate/1, connection_info/2, channel_info/3,
+ peer_addr/1, send_window/3, recv_window/3, adjust_window/3,
+ close/2, stop/1, send/5,
+ send_eof/2]).
+
+-export([open_channel/6, request/6, request/7, global_request/4, event/2,
+ cast/2]).
+
+%% Internal application API and spawn
+-export([send_msg/1, ssh_channel_info_handler/3]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(DBG_MESSAGE, true).
+
+-record(state,
+ {
+ role,
+ client,
+ starter,
+ connection, % pid()
+ connection_state, % #connection{}
+ latest_channel_id = 0,
+ opts,
+ channel_args,
+ connected
+ }).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+start_link(Opts) ->
+ gen_server:start_link(?MODULE, Opts, []).
+
+open_channel(ConnectionManager, ChannelType, ChannelSpecificData,
+ InitialWindowSize, MaxPacketSize, Timeout) ->
+ case (catch call(ConnectionManager, {open, self(), ChannelType,
+ InitialWindowSize,
+ MaxPacketSize, ChannelSpecificData},
+ Timeout)) of
+ {open, Channel} ->
+ {ok, Channel};
+ Error ->
+ %% TODO: Best way?
+ Error
+ end.
+
+request(ConnectionManager, ChannelPid, ChannelId, Type, true, Data, Timeout) ->
+ call(ConnectionManager, {request, ChannelPid, ChannelId, Type, Data}, Timeout);
+request(ConnectionManager, ChannelPid, ChannelId, Type, false, Data, _) ->
+ cast(ConnectionManager, {request, ChannelPid, ChannelId, Type, Data}).
+
+request(ConnectionManager, ChannelId, Type, true, Data, Timeout) ->
+ call(ConnectionManager, {request, ChannelId, Type, Data}, Timeout);
+request(ConnectionManager, ChannelId, Type, false, Data, _) ->
+ cast(ConnectionManager, {request, ChannelId, Type, Data}).
+
+global_request(ConnectionManager, Type, true = Reply, Data) ->
+ case call(ConnectionManager,
+ {global_request, self(), Type, Reply, Data}) of
+ {ssh_cm, ConnectionManager, {success, _}} ->
+ ok;
+ {ssh_cm, ConnectionManager, {failure, _}} ->
+ error
+ end;
+
+global_request(ConnectionManager, Type, false = Reply, Data) ->
+ cast(ConnectionManager, {global_request, self(), Type, Reply, Data}).
+
+event(ConnectionManager, BinMsg) ->
+ call(ConnectionManager, {ssh_msg, self(), BinMsg}).
+
+info(ConnectionManager) ->
+ info(ConnectionManager, {info, all}).
+
+info(ConnectionManager, ChannelProcess) ->
+ call(ConnectionManager, {info, ChannelProcess}).
+
+%% TODO: Do we really want this function? Should not
+%% renegotiation be triggered by configurable timer
+%% or amount of data sent counter!
+renegotiate(ConnectionManager) ->
+ cast(ConnectionManager, renegotiate).
+
+connection_info(ConnectionManager, Options) ->
+ call(ConnectionManager, {connection_info, Options}).
+
+channel_info(ConnectionManager, ChannelId, Options) ->
+ call(ConnectionManager, {channel_info, ChannelId, Options}).
+
+%% Replaced by option peer to connection_info/2 keep for now
+%% for Backwards compatibility!
+peer_addr(ConnectionManager) ->
+ call(ConnectionManager, {peer_addr, self()}).
+
+%% Backwards compatibility!
+send_window(ConnectionManager, Channel, TimeOut) ->
+ call(ConnectionManager, {send_window, Channel}, TimeOut).
+%% Backwards compatibility!
+recv_window(ConnectionManager, Channel, TimeOut) ->
+ call(ConnectionManager, {recv_window, Channel}, TimeOut).
+
+adjust_window(ConnectionManager, Channel, Bytes) ->
+ cast(ConnectionManager, {adjust_window, Channel, Bytes}).
+
+close(ConnectionManager, ChannelId) ->
+ try call(ConnectionManager, {close, ChannelId}) of
+ ok ->
+ ok
+ catch
+ exit:{noproc, _} ->
+ ok
+ end.
+
+stop(ConnectionManager) ->
+ try call(ConnectionManager, stop) of
+ ok ->
+ ok
+ catch
+ exit:{noproc, _} ->
+ ok
+ end.
+
+send(ConnectionManager, ChannelId, Type, Data, Timeout) ->
+ call(ConnectionManager, {data, ChannelId, Type, Data}, Timeout).
+
+send_eof(ConnectionManager, ChannelId) ->
+ cast(ConnectionManager, {eof, ChannelId}).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init([server, _Socket, Opts]) ->
+ process_flag(trap_exit, true),
+ ssh_bits:install_messages(ssh_connection:messages()),
+ Cache = ssh_channel:cache_create(),
+ {ok, #state{role = server,
+ connection_state = #connection{channel_cache = Cache,
+ channel_id_seed = 0,
+ port_bindings = [],
+ requests = [],
+ channel_pids = []},
+ opts = Opts,
+ connected = false}};
+
+init([client, Opts]) ->
+ process_flag(trap_exit, true),
+ {links, [Parent]} = process_info(self(), links),
+ ssh_bits:install_messages(ssh_connection:messages()),
+ Cache = ssh_channel:cache_create(),
+ Address = proplists:get_value(address, Opts),
+ Port = proplists:get_value(port, Opts),
+ SocketOpts = proplists:get_value(socket_opts, Opts),
+ Options = proplists:get_value(ssh_opts, Opts),
+ ChannelPid = proplists:get_value(channel_pid, Opts),
+ self() !
+ {start_connection, client, [Parent, Address, Port,
+ ChannelPid, SocketOpts, Options]},
+ {ok, #state{role = client,
+ client = ChannelPid,
+ connection_state = #connection{channel_cache = Cache,
+ channel_id_seed = 0,
+ port_bindings = [],
+ requests = [],
+ channel_pids = []},
+ opts = Opts,
+ connected = false}}.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+handle_call({request, ChannelPid, ChannelId, Type, Data}, From, State0) ->
+ {{replies, Replies}, State} = handle_request(ChannelPid,
+ ChannelId, Type, Data,
+ true, From, State0),
+ %% Sends message to the connection handler process, reply to
+ %% channel is sent later when reply arrives from the connection
+ %% handler.
+ lists:foreach(fun send_msg/1, Replies),
+ {noreply, State};
+
+handle_call({request, ChannelId, Type, Data}, From, State0) ->
+ {{replies, Replies}, State} = handle_request(ChannelId, Type, Data,
+ true, From, State0),
+ %% Sends message to the connection handler process, reply to
+ %% channel is sent later when reply arrives from the connection
+ %% handler.
+ lists:foreach(fun send_msg/1, Replies),
+ {noreply, State};
+
+%% Message from ssh_connection_handler
+handle_call({ssh_msg, Pid, Msg}, From,
+ #state{connection_state = Connection0,
+ role = Role, opts = Opts, connected = IsConnected,
+ client = ClientPid}
+ = State) ->
+
+ %% To avoid that not all data sent by the other side is processes before
+ %% possible crash in ssh_connection_handler takes down the connection.
+ gen_server:reply(From, ok),
+
+ ConnectionMsg = decode_ssh_msg(Msg),
+ try ssh_connection:handle_msg(ConnectionMsg, Connection0, Pid, Role) of
+ {{replies, Replies}, Connection} ->
+ lists:foreach(fun send_msg/1, Replies),
+ {noreply, State#state{connection_state = Connection}};
+ {noreply, Connection} ->
+ {noreply, State#state{connection_state = Connection}};
+ {disconnect, {_, Reason}, {{replies, Replies}, Connection}}
+ when Role == client andalso (not IsConnected) ->
+ lists:foreach(fun send_msg/1, Replies),
+ ClientPid ! {self(), not_connected, Reason},
+ {stop, normal, State#state{connection = Connection}};
+ {disconnect, Reason, {{replies, Replies}, Connection}} ->
+ lists:foreach(fun send_msg/1, Replies),
+ SSHOpts = proplists:get_value(ssh_opts, Opts),
+ disconnect_fun(Reason, SSHOpts),
+ {stop, normal, State#state{connection_state = Connection}}
+ catch
+ exit:{noproc, Reason} ->
+ Report = io_lib:format("Connection probably terminated:~n~p~n~p~n",
+ [ConnectionMsg, Reason]),
+ error_logger:info_report(Report),
+ {noreply, State};
+ error:Error ->
+ Report = io_lib:format("Connection message returned:~n~p~n~p~n",
+ [ConnectionMsg, Error]),
+ error_logger:info_report(Report),
+ {noreply, State};
+ exit:Exit ->
+ Report = io_lib:format("Connection message returned:~n~p~n~p~n",
+ [ConnectionMsg, Exit]),
+ error_logger:info_report(Report),
+ {noreply, State}
+ end;
+
+handle_call({global_request, Pid, _, _, _} = Request, From,
+ #state{connection_state =
+ #connection{channel_cache = Cache}} = State0) ->
+ State1 = handle_global_request(Request, State0),
+ Channel = ssh_channel:cache_find(Pid, Cache),
+ State = add_request(true, Channel#channel.local_id, From, State1),
+ {noreply, State};
+
+handle_call({data, ChannelId, Type, Data}, From,
+ #state{connection_state = #connection{channel_cache = _Cache}
+ = Connection0,
+ connection = ConnectionPid} = State) ->
+ channel_data(ChannelId, Type, Data, Connection0, ConnectionPid, From,
+ State);
+
+handle_call({connection_info, Options}, From,
+ #state{connection = Connection} = State) ->
+ ssh_connection_handler:connection_info(Connection, From, Options),
+ %% Reply will be sent by the connection handler by calling
+ %% ssh_connection_handler:send_msg/1.
+ {noreply, State};
+
+handle_call({channel_info, ChannelId, Options}, From,
+ #state{connection_state = #connection{channel_cache = Cache}} = State) ->
+
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{} = Channel ->
+ spawn(?MODULE, ssh_channel_info_handler, [Options, Channel, From]),
+ {noreply, State};
+ undefined ->
+ {reply, []}
+ end;
+
+handle_call({info, ChannelPid}, _From,
+ #state{connection_state =
+ #connection{channel_cache = Cache}} = State) ->
+ Result = ssh_channel:cache_foldl(
+ fun(Channel, Acc) when ChannelPid == all;
+ Channel#channel.user == ChannelPid ->
+ [Channel | Acc];
+ (_, Acc) ->
+ Acc
+ end, [], Cache),
+ {reply, {ok, Result}, State};
+
+handle_call({open, ChannelPid, Type, InitialWindowSize, MaxPacketSize, Data},
+ From, #state{connection = Pid,
+ connection_state =
+ #connection{channel_cache = Cache}} = State0) ->
+ {ChannelId, State1} = new_channel_id(State0),
+ Msg = ssh_connection:channel_open_msg(Type, ChannelId,
+ InitialWindowSize,
+ MaxPacketSize, Data),
+ send_msg({connection_reply, Pid, Msg}),
+ Channel = #channel{type = Type,
+ sys = "none",
+ user = ChannelPid,
+ local_id = ChannelId,
+ recv_window_size = InitialWindowSize,
+ recv_packet_size = MaxPacketSize},
+ ssh_channel:cache_update(Cache, Channel),
+ State = add_request(true, ChannelId, From, State1),
+ {noreply, State};
+
+handle_call({send_window, ChannelId}, _From,
+ #state{connection_state =
+ #connection{channel_cache = Cache}} = State) ->
+ Reply = case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{send_window_size = WinSize,
+ send_packet_size = Packsize} ->
+ {ok, {WinSize, Packsize}};
+ undefined ->
+ {error, einval}
+ end,
+ {reply, Reply, State};
+
+handle_call({recv_window, ChannelId}, _From,
+ #state{connection_state = #connection{channel_cache = Cache}}
+ = State) ->
+
+ Reply = case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{recv_window_size = WinSize,
+ recv_packet_size = Packsize} ->
+ {ok, {WinSize, Packsize}};
+ undefined ->
+ {error, einval}
+ end,
+ {reply, Reply, State};
+
+%% Replaced by option peer to connection_info/2 keep for now
+%% for Backwards compatibility!
+handle_call({peer_addr, _ChannelId}, _From,
+ #state{connection = Pid} = State) ->
+ Reply = ssh_connection_handler:peer_address(Pid),
+ {reply, Reply, State};
+
+handle_call(opts, _, #state{opts = Opts} = State) ->
+ {reply, Opts, State};
+
+handle_call({close, ChannelId}, _,
+ #state{connection = Pid, connection_state =
+ #connection{channel_cache = Cache}} = State) ->
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{remote_id = Id} ->
+ send_msg({connection_reply, Pid,
+ ssh_connection:channel_close_msg(Id)}),
+ {reply, ok, State};
+ undefined ->
+ {reply, ok, State}
+ end;
+
+handle_call(stop, _, #state{role = _client,
+ client = ChannelPid,
+ connection = Pid} = State) ->
+ DisconnectMsg =
+ #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "Application disconnect",
+ language = "en"},
+ (catch gen_fsm:send_all_state_event(Pid, DisconnectMsg)),
+% ssh_connection_handler:send(Pid, DisconnectMsg),
+ {stop, normal, ok, State};
+handle_call(stop, _, State) ->
+ {stop, normal, ok, State};
+
+%% API violation make it the violaters problem
+%% by ignoring it. The violating process will get
+%% a timeout or hang.
+handle_call(_, _, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast({request, ChannelPid, ChannelId, Type, Data}, State0) ->
+ {{replies, Replies}, State} = handle_request(ChannelPid, ChannelId,
+ Type, Data,
+ false, none, State0),
+ lists:foreach(fun send_msg/1, Replies),
+ {noreply, State};
+
+handle_cast({request, ChannelId, Type, Data}, State0) ->
+ {{replies, Replies}, State} = handle_request(ChannelId, Type, Data,
+ false, none, State0),
+ lists:foreach(fun send_msg/1, Replies),
+ {noreply, State};
+
+handle_cast({global_request, _, _, _, _} = Request, State0) ->
+ State = handle_global_request(Request, State0),
+ {noreply, State};
+
+handle_cast(renegotiate, #state{connection = Pid} = State) ->
+ ssh_connection_handler:renegotiate(Pid),
+ {noreply, State};
+
+handle_cast({adjust_window, ChannelId, Bytes},
+ #state{connection = Pid, connection_state =
+ #connection{channel_cache = Cache}} = State) ->
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{recv_window_size = WinSize, remote_id = Id} = Channel ->
+ ssh_channel:cache_update(Cache, Channel#channel{recv_window_size =
+ WinSize + Bytes}),
+ Msg = ssh_connection:channel_adjust_window_msg(Id, Bytes),
+ send_msg({connection_reply, Pid, Msg});
+ undefined ->
+ ignore
+ end,
+ {noreply, State};
+
+handle_cast({eof, ChannelId},
+ #state{connection = Pid, connection_state =
+ #connection{channel_cache = Cache}} = State) ->
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{remote_id = Id} ->
+ send_msg({connection_reply, Pid,
+ ssh_connection:channel_eof_msg(Id)}),
+ {noreply, State};
+ undefined ->
+ {noreply, State}
+ end;
+
+handle_cast({success, ChannelId}, #state{connection = Pid} = State) ->
+ Msg = ssh_connection:channel_success_msg(ChannelId),
+ send_msg({connection_reply, Pid, Msg}),
+ {noreply, State};
+
+handle_cast({failure, ChannelId}, #state{connection = Pid} = State) ->
+ Msg = ssh_connection:channel_failure_msg(ChannelId),
+ send_msg({connection_reply, Pid, Msg}),
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info({start_connection, server,
+ [Address, Port, Socket, Options]},
+ #state{connection_state = CState} = State) ->
+ {ok, Connection} = ssh_transport:accept(Address, Port, Socket, Options),
+ Shell = proplists:get_value(shell, Options),
+ Exec = proplists:get_value(exec, Options),
+ CliSpec = proplists:get_value(ssh_cli, Options, {ssh_cli, [Shell]}),
+ {noreply, State#state{connection = Connection,
+ connection_state =
+ CState#connection{address = Address,
+ port = Port,
+ cli_spec = CliSpec,
+ options = Options,
+ exec = Exec}}};
+
+handle_info({start_connection, client,
+ [Parent, Address, Port, ChannelPid, SocketOpts, Options]},
+ State) ->
+ case (catch ssh_transport:connect(Parent, Address,
+ Port, SocketOpts, Options)) of
+ {ok, Connection} ->
+ erlang:monitor(process, ChannelPid),
+ {noreply, State#state{connection = Connection}};
+ Reason ->
+ ChannelPid ! {self(), not_connected, Reason},
+ {stop, normal, State}
+ end;
+
+handle_info({ssh_cm, _Sender, Msg}, State0) ->
+ %% Backwards compatibility!
+ State = cm_message(Msg, State0),
+ {noreply, State};
+
+%% Nop backwards compatibility
+handle_info({same_user, _}, State) ->
+ {noreply, State};
+
+handle_info(ssh_connected, #state{role = client, client = Pid}
+ = State) ->
+ Pid ! {self(), is_connected},
+ {noreply, State#state{connected = true}};
+
+handle_info(ssh_connected, #state{role = server} = State) ->
+ {noreply, State#state{connected = true}};
+
+handle_info({'DOWN', _Ref, process, ChannelPid, normal}, State0) ->
+ handle_down(handle_channel_down(ChannelPid, State0));
+
+handle_info({'DOWN', _Ref, process, ChannelPid, shutdown}, State0) ->
+ handle_down(handle_channel_down(ChannelPid, State0));
+
+handle_info({'DOWN', _Ref, process, ChannelPid, Reason}, State0) ->
+ Report = io_lib:format("Pid ~p DOWN ~p\n", [ChannelPid, Reason]),
+ error_logger:error_report(Report),
+ handle_down(handle_channel_down(ChannelPid, State0));
+
+handle_info({'EXIT', _, _}, State) ->
+ %% Handled in 'DOWN'
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(Reason, #state{connection_state =
+ #connection{requests = Requests},
+ opts = Opts}) ->
+ SSHOpts = proplists:get_value(ssh_opts, Opts),
+ disconnect_fun(Reason, SSHOpts),
+ (catch lists:foreach(fun({_, From}) ->
+ gen_server:reply(From, {error, connection_closed})
+ end, Requests)),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+channel_data(Id, Type, Data, Connection0, ConnectionPid, From, State) ->
+ case ssh_connection:channel_data(Id, Type, Data, Connection0,
+ ConnectionPid, From) of
+ {{replies, Replies}, Connection} ->
+ lists:foreach(fun send_msg/1, Replies),
+ {noreply, State#state{connection_state = Connection}};
+ {noreply, Connection} ->
+ {noreply, State#state{connection_state = Connection}}
+ end.
+
+call(Pid, Msg) ->
+ call(Pid, Msg, infinity).
+call(Pid, Msg, Timeout) ->
+ try gen_server:call(Pid, Msg, Timeout) of
+ Result ->
+ Result
+ catch
+ exit:{timeout, _} ->
+ {error, timeout}
+ end.
+
+cast(Pid, Msg) ->
+ gen_server:cast(Pid, Msg).
+
+decode_ssh_msg(BinMsg) when is_binary(BinMsg)->
+ ssh_bits:decode(BinMsg);
+decode_ssh_msg(Msg) ->
+ Msg.
+
+
+send_msg(Msg) ->
+ case catch do_send_msg(Msg) of
+ {'EXIT', Reason}->
+ Report = io_lib:format("Connection Manager fail to send:~n~p~n"
+ "Reason why it failed was:~n~p~n",
+ [Msg, Reason]),
+ error_logger:info_report(Report);
+ _ ->
+ ok
+ end.
+
+do_send_msg({channel_data, Pid, Data}) ->
+ Pid ! {ssh_cm, self(), Data};
+do_send_msg({channel_requst_reply, From, Data}) ->
+ gen_server:reply(From, Data);
+do_send_msg({connection_reply, Pid, Data}) ->
+ Msg = ssh_bits:encode(Data),
+ ssh_connection_handler:send(Pid, Msg);
+do_send_msg({flow_control, Cache, Channel, From, Msg}) ->
+ ssh_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
+ gen_server:reply(From, Msg).
+
+handle_request(ChannelPid, ChannelId, Type, Data, WantReply, From,
+ #state{connection = Pid,
+ connection_state =
+ #connection{channel_cache = Cache}} = State0) ->
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{remote_id = Id} = Channel ->
+ update_sys(Cache, Channel, Type, ChannelPid),
+ Msg = ssh_connection:channel_request_msg(Id, Type,
+ WantReply, Data),
+ Replies = [{connection_reply, Pid, Msg}],
+ State = add_request(WantReply, ChannelId, From, State0),
+ {{replies, Replies}, State};
+ undefined ->
+ {{replies, []}, State0}
+ end.
+
+handle_request(ChannelId, Type, Data, WantReply, From,
+ #state{connection = Pid,
+ connection_state =
+ #connection{channel_cache = Cache}} = State0) ->
+ case ssh_channel:cache_lookup(Cache, ChannelId) of
+ #channel{remote_id = Id} ->
+ Msg = ssh_connection:channel_request_msg(Id, Type,
+ WantReply, Data),
+ Replies = [{connection_reply, Pid, Msg}],
+ State = add_request(WantReply, ChannelId, From, State0),
+ {{replies, Replies}, State};
+ undefined ->
+ {{replies, []}, State0}
+ end.
+
+handle_down({{replies, Replies}, State}) ->
+ lists:foreach(fun send_msg/1, Replies),
+ {noreply, State}.
+
+handle_channel_down(ChannelPid, #state{connection_state =
+ #connection{channel_cache = Cache}} =
+ State) ->
+ ssh_channel:cache_foldl(
+ fun(Channel, Acc) when Channel#channel.user == ChannelPid ->
+ ssh_channel:cache_delete(Cache,
+ Channel#channel.local_id),
+ Acc;
+ (_,Acc) ->
+ Acc
+ end, [], Cache),
+ {{replies, []}, State}.
+
+update_sys(Cache, Channel, Type, ChannelPid) ->
+ ssh_channel:cache_update(Cache,
+ Channel#channel{sys = Type, user = ChannelPid}).
+
+add_request(false, _ChannelId, _From, State) ->
+ State;
+add_request(true, ChannelId, From, #state{connection_state =
+ #connection{requests = Requests0} =
+ Connection} = State) ->
+ Requests = [{ChannelId, From} | Requests0],
+ State#state{connection_state = Connection#connection{requests = Requests}}.
+
+new_channel_id(#state{connection_state = #connection{channel_id_seed = Id} =
+ Connection}
+ = State) ->
+ {Id, State#state{connection_state =
+ Connection#connection{channel_id_seed = Id + 1}}}.
+
+handle_global_request({global_request, ChannelPid,
+ "tcpip-forward" = Type, WantReply,
+ <<?UINT32(IPLen),
+ IP:IPLen/binary, ?UINT32(Port)>> = Data},
+ #state{connection = ConnectionPid,
+ connection_state =
+ #connection{channel_cache = Cache}
+ = Connection0} = State) ->
+ ssh_channel:cache_update(Cache, #channel{user = ChannelPid,
+ type = "forwarded-tcpip",
+ sys = none}),
+ Connection = ssh_connection:bind(IP, Port, ChannelPid, Connection0),
+ Msg = ssh_connection:global_request_msg(Type, WantReply, Data),
+ send_msg({connection_reply, ConnectionPid, Msg}),
+ State#state{connection_state = Connection};
+
+handle_global_request({global_request, _Pid, "cancel-tcpip-forward" = Type,
+ WantReply, <<?UINT32(IPLen),
+ IP:IPLen/binary, ?UINT32(Port)>> = Data},
+ #state{connection = Pid,
+ connection_state = Connection0} = State) ->
+ Connection = ssh_connection:unbind(IP, Port, Connection0),
+ Msg = ssh_connection:global_request_msg(Type, WantReply, Data),
+ send_msg({connection_reply, Pid, Msg}),
+ State#state{connection_state = Connection};
+
+handle_global_request({global_request, _Pid, "cancel-tcpip-forward" = Type,
+ WantReply, Data}, #state{connection = Pid} = State) ->
+ Msg = ssh_connection:global_request_msg(Type, WantReply, Data),
+ send_msg({connection_reply, Pid, Msg}),
+ State.
+
+cm_message(Msg, State) ->
+ {noreply, NewState} = handle_cast(Msg, State),
+ NewState.
+
+disconnect_fun(Reason, Opts) ->
+ case proplists:get_value(disconnectfun, Opts) of
+ undefined ->
+ ok;
+ Fun ->
+ catch Fun(Reason)
+ end.
+
+ssh_channel_info_handler(Options, Channel, From) ->
+ Info = ssh_channel_info(Options, Channel, []),
+ send_msg({channel_requst_reply, From, Info}).
+
+ssh_channel_info([], _, Acc) ->
+ Acc;
+
+ssh_channel_info([recv_window | Rest], #channel{recv_window_size = WinSize,
+ recv_packet_size = Packsize
+ } = Channel, Acc) ->
+ ssh_channel_info(Rest, Channel, [{recv_window, {{win_size, WinSize},
+ {packet_size, Packsize}}} | Acc]);
+ssh_channel_info([send_window | Rest], #channel{send_window_size = WinSize,
+ send_packet_size = Packsize
+ } = Channel, Acc) ->
+ ssh_channel_info(Rest, Channel, [{send_window, {{win_size, WinSize},
+ {packet_size, Packsize}}} | Acc]);
+ssh_channel_info([ _ | Rest], Channel, Acc) ->
+ ssh_channel_info(Rest, Channel, Acc).
+
+
+
diff --git a/lib/ssh/src/ssh_dsa.erl b/lib/ssh/src/ssh_dsa.erl
new file mode 100755
index 0000000000..ec24fbcd01
--- /dev/null
+++ b/lib/ssh/src/ssh_dsa.erl
@@ -0,0 +1,95 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: dsa public-key sign and verify
+
+-module(ssh_dsa).
+
+-export([verify/3]).
+-export([sign/2]).
+-export([alg_name/0]).
+
+-include("ssh.hrl").
+
+%% start() ->
+%% crypto:start().
+
+%% sign_file(File, Opts) ->
+%% start(),
+%% {ok,Bin} = file:read_file(File),
+%% {ok,Key} = ssh_file:private_host_dsa_key(user, Opts),
+%% sign(Key, Bin).
+
+%% verify_file(File, Sig) ->
+%% start(),
+%% {ok,Bin} = file:read_file(File),
+%% {ok,Key} = ssh_file:public_host_key(user, dsa),
+%% verify(Key, Bin, Sig).
+
+sign(_Private=#ssh_key { private={P,Q,G,X} },Mb) ->
+ K = ssh_bits:irandom(160) rem Q,
+ R = ssh_math:ipow(G, K, P) rem Q,
+ Ki = ssh_math:invert(K, Q),
+ <<M:160/big-unsigned-integer>> = crypto:sha(Mb),
+ S = (Ki * (M + X*R)) rem Q,
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>.
+
+
+%% the paramiko client sends a bad sig sometimes,
+%% instead of crashing, we nicely return error, the
+%% typcally manifests itself as Sb being 39 bytes
+%% instead of 40.
+
+verify(Public, Mb, Sb) ->
+ case catch xverify(Public, Mb, Sb) of
+ {'EXIT', _Reason} ->
+ %store({Public, Mb, Sb, _Reason}),
+ {error, inconsistent_key};
+ ok ->
+ %store({Public, Mb, Sb, ok})
+ ok
+ end.
+
+%% store(Term) ->
+%% {ok, Fd} = file:open("/tmp/dsa", [append]),
+%% io:format(Fd, "~p~n~n~n", [Term]),
+%% file:close(Fd).
+
+
+xverify(_Public=#ssh_key { public={P,Q,G,Y} },Mb,Sb) ->
+ <<R0:160/big-unsigned-integer, S0:160/big-unsigned-integer>> = Sb,
+ ?ssh_assert(R0 >= 0 andalso R0 < Q andalso
+ S0 >= 0 andalso S0 < Q, out_of_range),
+ W = ssh_math:invert(S0,Q),
+ <<M0:160/big-unsigned-integer>> = crypto:sha(Mb),
+ U1 = (M0*W) rem Q,
+ U2 = (R0*W) rem Q,
+ T1 = ssh_math:ipow(G,U1,P),
+ T2 = ssh_math:ipow(Y,U2,P),
+ V = ((T1*T2) rem P) rem Q,
+ if V == R0 ->
+ ok;
+ true ->
+ {error, inconsistent_key}
+ end.
+
+alg_name() ->
+ "ssh-dss".
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
new file mode 100755
index 0000000000..8a3c903e51
--- /dev/null
+++ b/lib/ssh/src/ssh_file.erl
@@ -0,0 +1,530 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: SSH file handling
+
+-module(ssh_file).
+
+-include("ssh.hrl").
+-include("PKCS-1.hrl").
+-include("DSS.hrl").
+
+-export([public_host_dsa_key/2,private_host_dsa_key/2,
+ public_host_rsa_key/2,private_host_rsa_key/2,
+ public_host_key/2,private_host_key/2,
+ lookup_host_key/3, add_host_key/3, % del_host_key/2,
+ lookup_user_key/3, ssh_dir/2, file_name/3]).
+
+-export([private_identity_key/2]).
+%% , public_identity_key/2,
+%% identity_keys/2]).
+
+-export([encode_public_key/1, decode_public_key_v2/2]).
+
+-import(lists, [reverse/1, append/1]).
+
+-define(DBG_PATHS, true).
+
+%% API
+public_host_dsa_key(Type, Opts) ->
+ File = file_name(Type, "ssh_host_dsa_key.pub", Opts),
+ read_public_key_v2(File, "ssh-dss").
+
+private_host_dsa_key(Type, Opts) ->
+ File = file_name(Type, "ssh_host_dsa_key", Opts),
+ read_private_key_v2(File, "ssh-dss").
+
+public_host_rsa_key(Type, Opts) ->
+ File = file_name(Type, "ssh_host_rsa_key.pub", Opts),
+ read_public_key_v2(File, "ssh-rsa").
+
+private_host_rsa_key(Type, Opts) ->
+ File = file_name(Type, "ssh_host_rsa_key", Opts),
+ read_private_key_v2(File, "ssh-rsa").
+
+public_host_key(Type, Opts) ->
+ File = file_name(Type, "ssh_host_key", Opts),
+ case read_private_key_v1(File,public) of
+ {error, enoent} ->
+ read_public_key_v1(File++".pub");
+ Result ->
+ Result
+ end.
+
+
+private_host_key(Type, Opts) ->
+ File = file_name(Type, "ssh_host_key", Opts),
+ read_private_key_v1(File,private).
+
+
+
+%% in: "host" out: "host,1.2.3.4.
+add_ip(Host) ->
+ case inet:getaddr(Host, inet) of
+ {ok, Addr} ->
+ case ssh_connection:encode_ip(Addr) of
+ false -> Host;
+ IPString -> Host ++ "," ++ IPString
+ end;
+ _ -> Host
+ end.
+
+replace_localhost("localhost") ->
+ {ok, Hostname} = inet:gethostname(),
+ Hostname;
+replace_localhost(Host) ->
+ Host.
+
+%% lookup_host_key
+%% return {ok, Key(s)} or {error, not_found}
+%%
+
+lookup_host_key(Host, Alg, Opts) ->
+ Host1 = replace_localhost(Host),
+ do_lookup_host_key(Host1, Alg, Opts).
+
+do_lookup_host_key(Host, Alg, Opts) ->
+ case file:open(file_name(user, "known_hosts", Opts), [read]) of
+ {ok, Fd} ->
+ Res = lookup_host_key_fd(Fd, Host, Alg),
+ file:close(Fd),
+ Res;
+ {error, enoent} -> {error, not_found};
+ Error -> Error
+ end.
+
+add_host_key(Host, Key, Opts) ->
+ Host1 = add_ip(replace_localhost(Host)),
+ case file:open(file_name(user, "known_hosts", Opts),[write,append]) of
+ {ok, Fd} ->
+ Res = add_key_fd(Fd, Host1, Key),
+ file:close(Fd),
+ Res;
+ Error ->
+ Error
+ end.
+
+%% del_host_key(Host, Opts) ->
+%% Host1 = replace_localhost(Host),
+%% case file:open(file_name(user, "known_hosts", Opts),[write,read]) of
+%% {ok, Fd} ->
+%% Res = del_key_fd(Fd, Host1),
+%% file:close(Fd),
+%% Res;
+%% Error ->
+%% Error
+%% end.
+
+identity_key_filename("ssh-dss") -> "id_dsa";
+identity_key_filename("ssh-rsa") -> "id_rsa".
+
+private_identity_key(Alg, Opts) ->
+ Path = file_name(user, identity_key_filename(Alg), Opts),
+ read_private_key_v2(Path, Alg).
+
+read_public_key_v2(File, Type) ->
+ case file:read_file(File) of
+ {ok,Bin} ->
+ List = binary_to_list(Bin),
+ case lists:prefix(Type, List) of
+ true ->
+ List1 = lists:nthtail(length(Type), List),
+ K_S = ssh_bits:b64_decode(List1),
+ decode_public_key_v2(K_S, Type);
+ false ->
+ {error, bad_format}
+ end;
+ Error ->
+ Error
+ end.
+
+decode_public_key_v2(K_S, "ssh-rsa") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ {ok, #ssh_key { type = rsa,
+ public = {N,E},
+ comment=""}};
+ _ ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(K_S, "ssh-dss") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ {ok,#ssh_key { type = dsa,
+ public = {P,Q,G,Y}
+ }};
+ _A ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(_, _) ->
+ {error, bad_format}.
+
+
+read_public_key_v1(File) ->
+ case file:read_file(File) of
+ {ok,Bin} ->
+ List = binary_to_list(Bin),
+ case io_lib:fread("~d ~d ~d ~s", List) of
+ {ok,[_Sz,E,N,Comment],_} ->
+ {ok,#ssh_key { type = rsa,
+ public ={N,E},
+ comment = Comment }};
+ _Error ->
+ {error, bad_format}
+ end;
+ Error ->
+ Error
+ end.
+
+%% pem_type("ssh-dss") -> "DSA";
+%% pem_type("ssh-rsa") -> "RSA".
+
+read_private_key_v2(File, Type) ->
+ case catch (public_key:pem_to_der(File)) of
+ {ok, [{_, Bin, not_encrypted}]} ->
+ decode_private_key_v2(Bin, Type);
+ Error -> %% Note we do not handle password encrypted keys at the moment
+ {error, Error}
+ end.
+%% case file:read_file(File) of
+%% {ok,Bin} ->
+%% case read_pem(binary_to_list(Bin), pem_type(Type)) of
+%% {ok,Bin1} ->
+%% decode_private_key_v2(Bin1, Type);
+%% Error ->
+%% Error
+%% end;
+%% Error ->
+%% Error
+%% end.
+
+decode_private_key_v2(Private,"ssh-rsa") ->
+ case 'PKCS-1':decode( 'RSAPrivateKey', Private) of
+ {ok,RSA} -> %% FIXME Check for two-prime version
+ {ok, #ssh_key { type = rsa,
+ public = {RSA#'RSAPrivateKey'.modulus,
+ RSA#'RSAPrivateKey'.publicExponent},
+ private = {RSA#'RSAPrivateKey'.modulus,
+ RSA#'RSAPrivateKey'.privateExponent}
+ }};
+ Error ->
+ Error
+ end;
+decode_private_key_v2(Private, "ssh-dss") ->
+ case 'DSS':decode('DSAPrivateKey', Private) of
+ {ok,DSA} -> %% FIXME Check for two-prime version
+ {ok, #ssh_key { type = dsa,
+ public = {DSA#'DSAPrivateKey'.p,
+ DSA#'DSAPrivateKey'.q,
+ DSA#'DSAPrivateKey'.g,
+ DSA#'DSAPrivateKey'.y},
+ private= {DSA#'DSAPrivateKey'.p,
+ DSA#'DSAPrivateKey'.q,
+ DSA#'DSAPrivateKey'.g,
+ DSA#'DSAPrivateKey'.x}
+ }};
+ _ ->
+ {error,bad_format}
+ end.
+
+%% SSH1 private key format
+%% <<"SSH PRIVATE KEY FILE FORMATE 1.1\n" 0:8
+%% CipherNum:8, Reserved:32,
+%% NSz/uint32, N/bignum, E/bignum, Comment/string,
+%%
+%% [ R0:8 R1:8 R0:8 R1:8, D/bignum, IQMP/bignum, Q/bignum, P/bignum, Pad(8)]>>
+%%
+%% where [ ] is encrypted using des3 (ssh1 version) and
+%% a posssibly empty pass phrase using md5(passphase) as key
+%%
+
+read_private_key_v1(File, Type) ->
+ case file:read_file(File) of
+ {ok,<<"SSH PRIVATE KEY FILE FORMAT 1.1\n",0,
+ CipherNum,_Resereved:32,Bin/binary>>} ->
+ decode_private_key_v1(Bin, CipherNum,Type);
+ {ok,_} ->
+ {error, bad_format};
+ Error ->
+ Error
+ end.
+
+decode_private_key_v1(Bin, CipherNum, Type) ->
+ case ssh_bits:decode(Bin,0,[uint32, bignum, bignum, string]) of
+ {Offset,[_NSz,N,E,Comment]} ->
+ if Type == public ->
+ {ok,#ssh_key { type=rsa,
+ public={N,E},
+ comment=Comment}};
+ Type == private ->
+ <<_:Offset/binary, Encrypted/binary>> = Bin,
+ case ssh_bits:decode(decrypt1(Encrypted, CipherNum),0,
+ [uint32, bignum, bignum,
+ bignum, bignum,{pad,8}]) of
+ {_,[_,D,IQMP,Q,P]} ->
+ {ok,#ssh_key { type=rsa,
+ public={N,E},
+ private={D,IQMP,Q,P},
+ comment=Comment}};
+ _ ->
+ {error,bad_format}
+ end
+ end;
+ _ ->
+ {error,bad_format}
+ end.
+
+
+decrypt1(Bin, CipherNum) ->
+ decrypt1(Bin, CipherNum,"").
+
+decrypt1(Bin, CipherNum, Phrase) ->
+ if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
+ Bin;
+ CipherNum == ?SSH_CIPHER_3DES ->
+ <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
+ K3 = K1,
+ IV = <<0,0,0,0,0,0,0,0>>,
+ Bin1 = crypto:des_cbc_decrypt(K3,IV,Bin),
+ Bin2 = crypto:des_cbc_encrypt(K2,IV,Bin1),
+ crypto:des_cbc_decrypt(K1,IV,Bin2)
+ end.
+
+%% encrypt1(Bin, CipherNum) ->
+%% encrypt1(Bin, CipherNum,"").
+
+%% encrypt1(Bin, CipherNum, Phrase) ->
+%% if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
+%% Bin;
+%% CipherNum == ?SSH_CIPHER_3DES ->
+%% <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
+%% K3 = K1,
+%% IV = <<0,0,0,0,0,0,0,0>>,
+%% Bin1 = crypto:des_cbc_encrypt(K1,IV,Bin),
+%% Bin2 = crypto:des_cbc_decrypt(K2,IV,Bin1),
+%% crypto:des_cbc_encrypt(K3,IV,Bin2)
+%% end.
+
+lookup_host_key_fd(Fd, Host, Alg) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case string:tokens(Line, " ") of
+ [HostList, Alg, KeyData] ->
+%% io:format(" ~p lookup_host_key_fd: HostList ~p Alg ~p KeyData ~p\n",
+%% [Host, HostList, Alg, KeyData]),
+ case lists:member(Host, string:tokens(HostList, ",")) of
+ true ->
+ decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
+ false ->
+ lookup_host_key_fd(Fd, Host, Alg)
+ end;
+ _ ->
+ lookup_host_key_fd(Fd, Host, Alg)
+ end
+ end.
+
+
+
+%% del_key_fd(Fd, Host) ->
+%% del_key_fd(Fd, Host, 0, 0).
+
+%% del_key_fd(Fd, Host, ReadPos0, WritePos0) ->
+%% case io:get_line(Fd, '') of
+%% eof ->
+%% if ReadPos0 == WritePos0 ->
+%% ok;
+%% true ->
+%% file:truncate(Fd)
+%% end;
+%% Line ->
+%% {ok,ReadPos1} = file:position(Fd, cur),
+%% case string:tokens(Line, " ") of
+%% [HostList, _Type, _KeyData] ->
+%% case lists:member(Host, string:tokens(HostList, ",")) of
+%% true ->
+%% del_key_fd(Fd, Host, ReadPos1, WritePos0);
+%% false ->
+%% if ReadPos0 == WritePos0 ->
+%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
+%% true ->
+%% file:position(Fd, WritePos0),
+%% file:write(Fd, Line),
+%% {ok,WritePos1} = file:position(Fd,cur),
+%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
+%% end
+%% end;
+%% _ ->
+%% if ReadPos0 == WritePos0 ->
+%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
+%% true ->
+%% file:position(Fd, WritePos0),
+%% file:write(Fd, Line),
+%% {ok,WritePos1} = file:position(Fd,cur),
+%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
+%% end
+%% end
+%% end.
+
+
+add_key_fd(Fd, Host, Key) ->
+ case Key#ssh_key.type of
+ rsa ->
+ {N,E} = Key#ssh_key.public,
+ DK = ssh_bits:b64_encode(
+ ssh_bits:encode(["ssh-rsa",E,N],
+ [string,mpint,mpint])),
+ file:write(Fd, [Host, " ssh-rsa ", DK, "\n"]);
+ dsa ->
+ {P,Q,G,Y} = Key#ssh_key.public,
+ DK = ssh_bits:b64_encode(
+ ssh_bits:encode(["ssh-dss",P,Q,G,Y],
+ [string,mpint,mpint,mpint,mpint])),
+ file:write(Fd, [Host, " ssh-dss ", DK, "\n"])
+ end.
+
+
+%% read_pem(Cs, Type) ->
+%% case read_line(Cs) of
+%% {"-----BEGIN "++Rest,Cs1} ->
+%% case string:tokens(Rest, " ") of
+%% [Type, "PRIVATE", "KEY-----"] ->
+%% read_pem64(Cs1, [], Type);
+%% _ ->
+%% {error, bad_format}
+%% end;
+%% {"",Cs1} when Cs1 =/= "" ->
+%% read_pem(Cs1,Type);
+%% {_,""} ->
+%% {error, bad_format}
+%% end.
+
+%% read_pem64(Cs, Acc, Type) ->
+%% case read_line(Cs) of
+%% {"-----END "++Rest,_Cs1} ->
+%% case string:tokens(Rest, " ") of
+%% [Type, "PRIVATE", "KEY-----"] ->
+%% {ok,ssh_bits:b64_decode(append(reverse(Acc)))};
+%% Toks ->
+%% error_logger:format("ssh: TOKENS=~p\n", [Toks]),
+%% {error, bad_format}
+%% end;
+%% {B64, Cs1} when Cs1 =/= "" ->
+%% read_pem64(Cs1, [B64|Acc], Type);
+%% _What ->
+%% {error, bad_format}
+%% end.
+
+
+%% read_line(Cs) -> read_line(Cs,[]).
+%% read_line([$\r,$\n|T], Acc) -> {reverse(Acc), T};
+%% read_line([$\n|T], Acc) -> {reverse(Acc), T};
+%% read_line([C|T], Acc) -> read_line(T,[C|Acc]);
+%% read_line([], Acc) -> {reverse(Acc),[]}.
+
+lookup_user_key(User, Alg, Opts) ->
+ SshDir = ssh_dir({remoteuser,User}, Opts),
+ case lookup_user_key_f(User, SshDir, Alg, "authorized_keys", Opts) of
+ {ok, Key} ->
+ {ok, Key};
+ _ ->
+ lookup_user_key_f(User, SshDir, Alg, "authorized_keys2", Opts)
+ end.
+
+lookup_user_key_f(_User, [], _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(_User, nouserdir, _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(_User, Dir, Alg, F, _Opts) ->
+ FileName = filename:join(Dir, F),
+ case file:open(FileName, [read]) of
+ {ok, Fd} ->
+ Res = lookup_user_key_fd(Fd, Alg),
+ file:close(Fd),
+ Res;
+ {error, Reason} ->
+ {error, {{openerr, Reason}, {file, FileName}}}
+ end.
+
+lookup_user_key_fd(Fd, Alg) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case string:tokens(Line, " ") of
+ [Alg, KeyData, _] ->
+ %% io:format("lookup_user_key_fd: HostList ~p Alg ~p KeyData ~p\n",
+ %% [HostList, Alg, KeyData]),
+ decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
+ _Other ->
+ %%?dbg(false, "key_fd Other: ~w ~w\n", [Alg, _Other]),
+ lookup_user_key_fd(Fd, Alg)
+ end
+ end.
+
+
+encode_public_key(#ssh_key{type = rsa, public = {N, E}}) ->
+ ssh_bits:encode(["ssh-rsa",E,N],
+ [string,mpint,mpint]);
+encode_public_key(#ssh_key{type = dsa, public = {P,Q,G,Y}}) ->
+ ssh_bits:encode(["ssh-dss",P,Q,G,Y],
+ [string,mpint,mpint,mpint,mpint]).
+
+%%
+%% Utils
+%%
+
+%% server use this to find individual keys for
+%% an individual user when user tries to login
+%% with publickey
+ssh_dir({remoteuser, User}, Opts) ->
+ case proplists:get_value(user_dir_fun, Opts) of
+ undefined ->
+ case proplists:get_value(user_dir, Opts) of
+ undefined ->
+ default_user_dir();
+ Dir ->
+ Dir
+ end;
+ FUN ->
+ FUN(User)
+ end;
+
+%% client use this to find client ssh keys
+ssh_dir(user, Opts) ->
+ case proplists:get_value(user_dir, Opts, false) of
+ false -> default_user_dir();
+ D -> D
+ end;
+
+%% server use this to find server host keys
+ssh_dir(system, Opts) ->
+ proplists:get_value(system_dir, Opts, "/etc/ssh").
+
+file_name(Type, Name, Opts) ->
+ FN = filename:join(ssh_dir(Type, Opts), Name),
+ %%?dbg(?DBG_PATHS, "file_name: ~p\n", [FN]),
+ FN.
+
+default_user_dir()->
+ {ok,[[Home|_]]} = init:get_argument(home),
+ filename:join(Home, ".ssh").
diff --git a/lib/ssh/src/ssh_io.erl b/lib/ssh/src/ssh_io.erl
new file mode 100755
index 0000000000..0e343c20b4
--- /dev/null
+++ b/lib/ssh/src/ssh_io.erl
@@ -0,0 +1,79 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: user interaction for SSH
+
+-module(ssh_io).
+
+-export([yes_no/1, read_password/1, read_line/1, format/2]).
+-import(lists, [reverse/1]).
+
+
+read_line(Prompt) when is_list(Prompt) ->
+ io:get_line(list_to_atom(Prompt));
+read_line(Prompt) when is_atom(Prompt) ->
+ io:get_line(Prompt).
+
+read_ln(Prompt) ->
+ trim(read_line(Prompt)).
+
+yes_no(Prompt) ->
+ io:format("~s [y/n]?", [Prompt]),
+ case read_ln('') of
+ "y" -> yes;
+ "n" -> no;
+ "Y" -> yes;
+ "N" -> no;
+ _ ->
+ io:format("please answer y or n\n"),
+ yes_no(Prompt)
+ end.
+
+
+read_password(Prompt) ->
+ format("~s", [listify(Prompt)]),
+ case io:get_password() of
+ "" ->
+ read_password(Prompt);
+ Pass -> Pass
+ end.
+
+listify(A) when is_atom(A) ->
+ atom_to_list(A);
+listify(L) when is_list(L) ->
+ L.
+
+format(Fmt, Args) ->
+ io:format(Fmt, Args).
+
+
+trim(Line) when is_list(Line) ->
+ reverse(trim1(reverse(trim1(Line))));
+trim(Other) -> Other.
+
+trim1([$\s|Cs]) -> trim(Cs);
+trim1([$\r|Cs]) -> trim(Cs);
+trim1([$\n|Cs]) -> trim(Cs);
+trim1([$\t|Cs]) -> trim(Cs);
+trim1(Cs) -> Cs.
+
+
+
diff --git a/lib/ssh/src/ssh_math.erl b/lib/ssh/src/ssh_math.erl
new file mode 100755
index 0000000000..efe7f56979
--- /dev/null
+++ b/lib/ssh/src/ssh_math.erl
@@ -0,0 +1,131 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: SSH math utilities
+
+-module(ssh_math).
+
+-export([ilog2/1, ipow/3, invert/2, ipow2/3]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% INTEGER utils
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% number of bits (used) in a integer = isize(N) = |log2(N)|+1
+ilog2(N) ->
+ ssh_bits:isize(N) - 1.
+
+
+%% calculate A^B mod M
+ipow(A, B, M) when M > 0, B >= 0 ->
+ crypto:mod_exp(A, B, M).
+
+ipow2(A, B, M) when M > 0, B >= 0 ->
+ if A == 1 ->
+ 1;
+ true ->
+ ipow2(A, B, M, 1)
+ end.
+
+ipow2(A, 1, M, Prod) ->
+ (A*Prod) rem M;
+ipow2(_A, 0, _M, Prod) ->
+ Prod;
+ipow2(A, B, M, Prod) ->
+ B1 = B bsr 1,
+ A1 = (A*A) rem M,
+ if B - B1 == B1 ->
+ ipow2(A1, B1, M, Prod);
+ true ->
+ ipow2(A1, B1, M, (A*Prod) rem M)
+ end.
+
+%% %%
+%% %% Normal gcd
+%% %%
+%% gcd(R, Q) when abs(Q) < abs(R) -> gcd1(Q,R);
+%% gcd(R, Q) -> gcd1(R,Q).
+
+%% gcd1(0, Q) -> Q;
+%% gcd1(R, Q) ->
+%% gcd1(Q rem R, R).
+
+
+%% %%
+%% %% Least common multiple of (R,Q)
+%% %%
+%% lcm(0, _Q) -> 0;
+%% lcm(_R, 0) -> 0;
+%% lcm(R, Q) ->
+%% (Q div gcd(R, Q)) * R.
+
+%% %%
+%% %% Extended gcd gcd(R,Q) -> {G, {A,B}} such that G == R*A + Q*B
+%% %%
+%% %% Here we could have use for a bif divrem(Q, R) -> {Quote, Remainder}
+%% %%
+%% egcd(R,Q) when abs(Q) < abs(R) -> egcd1(Q,R,1,0,0,1);
+%% egcd(R,Q) -> egcd1(R,Q,0,1,1,0).
+
+%% egcd1(0,Q,_,_,Q1,Q2) -> {Q, {Q2,Q1}};
+%% egcd1(R,Q,R1,R2,Q1,Q2) ->
+%% D = Q div R,
+%% egcd1(Q rem R, R, Q1-D*R1, Q2-D*R2, R1, R2).
+
+%%
+%% Invert an element X mod P
+%% Calculated as {1, {A,B}} = egcd(X,P),
+%% 1 == P*A + X*B == X*B (mod P) i.e B is the inverse element
+%%
+%% X > 0, P > 0, X < P (P should be prime)
+%%
+invert(X,P) when X > 0, P > 0, X < P ->
+ I = inv(X,P,1,0),
+ if
+ I < 0 -> P + I;
+ true -> I
+ end.
+
+inv(0,_,_,Q) -> Q;
+inv(X,P,R1,Q1) ->
+ D = P div X,
+ inv(P rem X, X, Q1 - D*R1, R1).
+
+
+%% %%
+%% %% Integer square root
+%% %%
+
+%% isqrt(0) -> 0;
+%% isqrt(1) -> 1;
+%% isqrt(X) when X >= 0 ->
+%% R = X div 2,
+%% isqrt(X div R, R, X).
+
+%% isqrt(Q,R,X) when Q < R ->
+%% R1 = (R+Q) div 2,
+%% isqrt(X div R1, R1, X);
+%% isqrt(_, R, _) -> R.
+
+
diff --git a/lib/ssh/src/ssh_no_io.erl b/lib/ssh/src/ssh_no_io.erl
new file mode 100644
index 0000000000..5f363ae6c2
--- /dev/null
+++ b/lib/ssh/src/ssh_no_io.erl
@@ -0,0 +1,39 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: ssh_io replacement that throws on everything
+
+-module(ssh_no_io).
+
+-export([yes_no/1, read_password/1, read_line/1, format/2]).
+
+yes_no(_Prompt) ->
+ throw({no_io_allowed, yes_no}).
+
+read_password(_Prompt) ->
+ throw({no_io_allowed, read_password}).
+
+read_line(_Prompt) ->
+ throw({no_io_allowed, read_line}).
+
+format(_Fmt, _Args) ->
+ throw({no_io_allowed, format}).
+
diff --git a/lib/ssh/src/ssh_rsa.erl b/lib/ssh/src/ssh_rsa.erl
new file mode 100755
index 0000000000..7c2bf9a2bf
--- /dev/null
+++ b/lib/ssh/src/ssh_rsa.erl
@@ -0,0 +1,299 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: rsa public-key sign and verify
+
+-module(ssh_rsa).
+
+-export([verify/3, sign/2]).
+-export([alg_name/0]).
+
+-include("ssh.hrl").
+-include("PKCS-1.hrl").
+
+
+-define(MGF(Seed,Len), mgf1((Seed),(Len))).
+-define(HASH(X), crypto:sha((X))).
+-define(HLen, 20).
+
+%% start() ->
+%% crypto:start().
+
+%% sign_file(File) ->
+%% start(),
+%% {ok,Bin} = file:read_file(File),
+%% {ok,Key} = ssh_file:private_host_rsa_key(user),
+%% sign(Key, Bin).
+
+%% verify_file(File, Sig) ->
+%% start(),
+%% {ok,Bin} = file:read_file(File),
+%% {ok,Key} = ssh_file:public_host_rsa_key(user),
+%% verify(Key, Bin, Sig).
+
+sign(Private,Mb) ->
+ rsassa_pkcs1_v1_5_sign(Private,Mb).
+
+verify(Public,Mb,Sb) ->
+ rsassa_pkcs1_v1_5_verify(Public,Mb,Sb).
+
+
+
+%% Integer to octet string
+i2osp(X, XLen) ->
+ ssh_bits:i2bin(X, XLen).
+
+%% Octet string to Integer
+os2ip(X) ->
+ ssh_bits:bin2i(X).
+
+%% decrypt1, M = message representative
+%% rsaep(#ssh_key { public={N,E}}, M) ->
+%% ?ssh_assert(M >= 0 andalso M =< N-1, out_of_range),
+%% ssh_math:ipow(M, E, N).
+
+%% encrypt1, C = cipher representative
+%% rsadp(#ssh_key { public={N,_}, private={_,D}}, C) ->
+%% ?ssh_assert(C >= 0 andalso C =< N-1, out_of_range),
+%% ssh_math:ipow(C, D, N).
+
+%% sign1, M = message representative
+rsasp1(#ssh_key { public={N,_}, private={_,D}}, M) ->
+ ?ssh_assert((M >= 0 andalso M =< N-1), out_of_range),
+ ssh_math:ipow(M, D, N).
+
+%% verify1, S =signature representative
+rsavp1(#ssh_key { public={N,E}}, S) ->
+ ?ssh_assert(S >= 0 andalso S =< N-1, out_of_range),
+ ssh_math:ipow(S, E, N).
+
+
+%% M messaage
+%% rsaes_oaep_encrypt(Public, M) ->
+%% rsaes_oaep_encrypt(Public, M, <<>>).
+
+%% rsaes_oaep_encrypt(Public=#ssh_key { public={N,_E}}, M, L) ->
+%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
+%% K = (ssh_bits:isize(N)+7) div 8,
+%% MLen = size(M),
+%% %% LLen = size(L),
+%% ?ssh_assert(MLen =< K - 2*?HLen - 2, message_to_long),
+%% LHash = ?HASH(L),
+%% PS = ssh_bits:fill_bits(K - MLen - 2*?HLen - 2, 0),
+%% DB = <<LHash/binary, PS/binary, 16#01, M/binary>>,
+%% Seed = ssh_bits:random(?HLen),
+%% DbMask = ?MGF(Seed, K - ?HLen - 1),
+%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
+%% SeedMask = ?MGF(MaskedDB, ?HLen),
+%% MaskedSeed = ssh_bits:xor_bits(Seed, SeedMask),
+%% EM = <<16#00, MaskedSeed/binary, MaskedDB/binary>>,
+%% Mc = os2ip(EM),
+%% C = rsaep(Public, Mc),
+%% i2osp(C, K).
+
+%% rsaes_oaep_decrypt(Key, C) ->
+%% rsaes_oaep_decrypt(Key, C, <<>>).
+
+%% rsaes_oaep_decrypt(Private=#ssh_key { public={N,_},private={_,_}},Cb,L) ->
+%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
+%% K = (ssh_bits:isize(N)+7) div 8,
+%% ?ssh_assert(K == 2*?HLen + 2, decryption_error),
+%% C = os2ip(Cb),
+%% M = rsadp(Private, C),
+%% EM = i2osp(M, K),
+%% LHash = ?HASH(L),
+%% MLen = K - ?HLen -1,
+%% case EM of
+%% <<16#00, MaskedSeed:?HLen/binary, MaskedDB:MLen>> ->
+%% SeedMask = ?MGF(MaskedDB, ?HLen),
+%% Seed = ssh_bits:xor_bits(MaskedSeed, SeedMask),
+%% DbMask = ?MGF(Seed, K - ?HLen - 1),
+%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
+%% PSLen = K - MLen - 2*?HLen - 2,
+%% case DB of
+%% <<LHash:?HLen, _PS:PSLen/binary, 16#01, M/binary>> ->
+%% M;
+%% _ ->
+%% exit(decryption_error)
+%% end;
+%% _ ->
+%% exit(decryption_error)
+%% end.
+
+
+%% rsaes_pkcs1_v1_5_encrypt(Public=#ssh_key { public={N,_}}, M) ->
+%% K = (ssh_bits:isize(N)+7) div 8,
+%% MLen = size(M),
+%% ?ssh_assert(MLen =< K - 11, message_to_long),
+%% PS = ssh_bits:random(K - MLen - 3),
+%% EM = <<16#00,16#02,PS/binary,16#00,M/binary>>,
+%% Mc = os2ip(EM),
+%% C = rsaep(Public, Mc),
+%% i2osp(C, K).
+
+
+%% rsaes_pkcs1_v1_5_decrypt(Private=#ssh_key { public={N,_},private={_,_}},
+%% Cb) ->
+%% K = (ssh_bits:isize(N)+7) div 8,
+%% CLen = size(Cb),
+%% ?ssh_assert(CLen == K andalso K >= 11, decryption_error),
+%% C = os2ip(Cb),
+%% M = rsadp(Private, C),
+%% EM = i2osp(M, K),
+%% PSLen = K - CLen - 3,
+%% case EM of
+%% <<16#00, 16#02, _PS:PSLen/binary, 16#00, M>> ->
+%% M;
+%% _ ->
+%% exit(decryption_error)
+%% end.
+
+%% rsassa_pss_sign(Private=#ssh_key { public={N,_},private={_,_}},Mb) ->
+%% ModBits = ssh_bits:isize(N),
+%% K = (ModBits+7) div 8,
+%% EM = emsa_pss_encode(Mb, ModBits - 1),
+%% M = os2ip(EM),
+%% S = rsasp1(Private, M),
+%% i2osp(S, K).
+
+%% rsassa_pss_verify(Public=#ssh_key { public={N,_E}},Mb,Sb) ->
+%% ModBits = ssh_bits:isize(N),
+%% K = (ModBits+7) div 8,
+%% ?ssh_assert(size(Sb) == K, invalid_signature),
+%% S = os2ip(Sb),
+%% M = rsavp1(Public,S),
+%% EMLen = (ModBits-1+7) div 8,
+%% EM = i2osp(M, EMLen),
+%% emsa_pss_verify(Mb, EM, ModBits-1).
+
+
+rsassa_pkcs1_v1_5_sign(Private=#ssh_key { public={N,_},private={_,_D}},Mb) ->
+ K = (ssh_bits:isize(N)+7) div 8,
+ EM = emsa_pkcs1_v1_5_encode(Mb, K),
+ M = os2ip(EM),
+ S = rsasp1(Private, M),
+ i2osp(S, K).
+
+rsassa_pkcs1_v1_5_verify(Public=#ssh_key { public={N,_E}}, Mb, Sb) ->
+ K = (ssh_bits:isize(N)+7) div 8,
+ ?ssh_assert(size(Sb) == K, invalid_signature),
+ S = os2ip(Sb),
+ M = rsavp1(Public, S),
+ EM = i2osp(M, K),
+ %?dbg(true, "verify K=~p S=~w ~n#M=~w~n#EM=~w~n", [K, S, M, EM]),
+ case emsa_pkcs1_v1_5_encode(Mb, K) of
+ EM -> ok;
+ _S ->
+ io:format("S: ~p~n", [_S]),
+ {error, invalid_signature} % exit(invalid_signature)
+ end.
+
+
+emsa_pkcs1_v1_5_encode(M, EMLen) ->
+ H = ?HASH(M),
+ %% Must use speical xxNull types here!
+ Alg = #'AlgorithmNull' { algorithm = ?'id-sha1',
+ parameters = <<>> },
+ {ok,TCode} = 'PKCS-1':encode('DigestInfoNull',
+ #'DigestInfoNull'{ digestAlgorithm = Alg,
+ digest = H }),
+ T = list_to_binary(TCode),
+ TLen = size(T),
+ ?ssh_assert(EMLen >= TLen + 11, message_to_short),
+ PS = ssh_bits:fill_bits(EMLen - TLen - 3, 16#ff),
+ <<16#00, 16#01, PS/binary, 16#00, T/binary>>.
+
+
+%% emsa_pss_encode(M, EMBits) ->
+%% emsa_pss_encode(M, EMBits, 0).
+
+%% emsa_pss_encode(M, EMBits, SLen) ->
+%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
+%% EMLen = (EMBits + 7) div 8,
+%% MHash = ?HASH(M),
+%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, encoding_error),
+%% Salt = ssh_bits:random(SLen),
+%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+%% MHash, Salt],
+%% H = ?HASH(M1),
+%% PS = ssh_bits:fill_bits(EMLen-SLen-?HLen-2, 0),
+%% DB = <<PS/binary, 16#01, Salt/binary>>,
+%% DbMask = ?MGF(H, EMLen - ?HLen -1),
+%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
+%% ZLen = 8*EMLen - EMBits,
+%% NZLen = (8 - (ZLen rem 8)) rem 8,
+%% <<_:ZLen, NZ:NZLen, MaskedDB1/binary>> = MaskedDB,
+%% MaskedDB2 = <<0:ZLen, NZ:NZLen, MaskedDB1/binary>>,
+%% <<MaskedDB2/binary, H/binary, 16#BC>>.
+
+
+%% emsa_pss_verify(M, EM, EMBits) ->
+%% emsa_pss_verify(M, EM, EMBits, 0).
+
+%% emsa_pss_verify(M, EM, EMBits, SLen) ->
+%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
+%% EMLen = (EMBits + 7) div 8,
+%% MHash = ?HASH(M),
+%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, inconsistent),
+%% MaskLen = (EMLen - ?HLen - 1)-1,
+%% ZLen = 8*EMLen - EMBits,
+%% NZLen = (8 - (ZLen rem 8)) rem 8,
+%% case EM of
+%% <<0:ZLen,Nz:NZLen,MaskedDB1:MaskLen/binary, H:?HLen/binary, 16#BC>> ->
+%% MaskedDB = <<0:ZLen,Nz:NZLen,MaskedDB1/binary>>,
+%% DbMask = ?MGF(H, EMLen - ?HLen - 1),
+%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
+%% PSLen1 = (EMLen - SLen - ?HLen - 2) - 1,
+%% PS = ssh_bits:fill_bits(PSLen1, 0),
+%% case DB of
+%% <<_:ZLen,0:NZLen,PS:PSLen1/binary,16#01,Salt:SLen/binary>> ->
+%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
+%% MHash, Salt],
+%% case ?HASH(M1) of
+%% H -> ok;
+%% _ -> exit(inconsistent)
+%% end;
+%% _ ->
+%% exit(inconsistent)
+%% end;
+%% _ ->
+%% exit(inconsistent)
+%% end.
+
+
+
+%% Mask generating function MGF1
+%% mgf1(MGFSeed, MaskLen) ->
+%% T = mgf1_loop(0, ((MaskLen + ?HLen -1) div ?HLen) - 1, MGFSeed, ""),
+%% <<R:MaskLen/binary, _/binary>> = T,
+%% R.
+
+%% mgf1_loop(Counter, N, _, T) when Counter > N ->
+%% list_to_binary(T);
+%% mgf1_loop(Counter, N, MGFSeed, T) ->
+%% C = i2osp(Counter, 4),
+%% mgf1_loop(Counter+1, N, MGFSeed, [T, ?HASH([MGFSeed, C])]).
+
+
+
+
+alg_name() ->
+ "ssh-rsa".
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
new file mode 100755
index 0000000000..cbfa208f6f
--- /dev/null
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -0,0 +1,1148 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: SFTP protocol front-end
+
+-module(ssh_sftp).
+
+-behaviour(ssh_channel).
+
+-include_lib("kernel/include/file.hrl").
+-include("ssh.hrl").
+-include("ssh_xfer.hrl").
+
+%% API
+
+-export([start_channel/1, start_channel/2, start_channel/3, stop_channel/1]).
+
+-export([open/3, opendir/2, close/2, readdir/2, pread/4, read/3,
+ open/4, opendir/3, close/3, readdir/3, pread/5, read/4,
+ apread/4, aread/3, pwrite/4, write/3, apwrite/4, awrite/3,
+ pwrite/5, write/4,
+ position/3, real_path/2, read_file_info/2, get_file_info/2,
+ position/4, real_path/3, read_file_info/3, get_file_info/3,
+ write_file_info/3, read_link_info/2, read_link/2, make_symlink/3,
+ write_file_info/4, read_link_info/3, read_link/3, make_symlink/4,
+ rename/3, delete/2, make_dir/2, del_dir/2, send_window/1,
+ rename/4, delete/3, make_dir/3, del_dir/3, send_window/2,
+ recv_window/1, list_dir/2, read_file/2, write_file/3,
+ recv_window/2, list_dir/3, read_file/3, write_file/4]).
+
+%% Deprecated
+-export([connect/1, connect/2, connect/3, stop/1]).
+
+-deprecated({connect, 1, next_major_release}).
+-deprecated({connect, 2, next_major_release}).
+-deprecated({connect, 3, next_major_release}).
+-deprecated({stop, 1, next_major_release}).
+
+%% ssh_channel callbacks
+-export([init/1, handle_call/3, handle_msg/2, handle_ssh_msg/2, terminate/2]).
+%% TODO: Should be placed elsewhere ssh_sftpd should not call functions in ssh_sftp!
+-export([info_to_attr/1, attr_to_info/1]).
+
+-record(state,
+ {
+ xf,
+ rep_buf = <<>>,
+ req_id,
+ req_list = [], %% {ReqId, Fun}
+ inf %% list of fileinf
+ }).
+
+-record(fileinf,
+ {
+ handle,
+ offset,
+ size,
+ mode
+ }).
+
+-define(FILEOP_TIMEOUT, infinity).
+
+-define(NEXT_REQID(S),
+ S#state { req_id = (S#state.req_id + 1) band 16#ffffffff}).
+
+-define(XF(S), S#state.xf).
+-define(REQID(S), S#state.req_id).
+
+%%====================================================================
+%% API
+%%====================================================================
+start_channel(Cm) when is_pid(Cm) ->
+ start_channel(Cm, []);
+start_channel(Host) when is_list(Host) ->
+ start_channel(Host, []).
+start_channel(Cm, Opts) when is_pid(Cm) ->
+ Timeout = proplists:get_value(timeout, Opts, infinity),
+ case ssh_xfer:attach(Cm, []) of
+ {ok, ChannelId, Cm} ->
+ case ssh_channel:start(Cm, ChannelId,
+ ?MODULE, [Cm, ChannelId, Timeout]) of
+ {ok, Pid} ->
+ case wait_for_version_negotiation(Pid, Timeout) of
+ ok ->
+ {ok, Pid};
+ TimeOut ->
+ TimeOut
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ ignore ->
+ {error, ignore}
+ end;
+ Error ->
+ Error
+ end;
+
+start_channel(Host, Opts) ->
+ start_channel(Host, 22, Opts).
+start_channel(Host, Port, Opts) ->
+ Timeout = proplists:get_value(timeout, Opts, infinity),
+ case ssh_xfer:connect(Host, Port, proplists:delete(timeout, Opts)) of
+ {ok, ChannelId, Cm} ->
+ case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm,
+ ChannelId, Timeout]) of
+ {ok, Pid} ->
+ case wait_for_version_negotiation(Pid, Timeout) of
+ ok ->
+ {ok, Pid, Cm};
+ TimeOut ->
+ TimeOut
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ ignore ->
+ {error, ignore}
+ end;
+ Error ->
+ Error
+ end.
+
+stop_channel(Pid) ->
+ case process_info(Pid, [trap_exit]) of
+ [{trap_exit, Bool}] ->
+ process_flag(trap_exit, true),
+ link(Pid),
+ exit(Pid, ssh_sftp_stop_channel),
+ receive
+ {'EXIT', Pid, normal} ->
+ ok
+ after 5000 ->
+ exit(Pid, kill),
+ receive
+ {'EXIT', Pid, killed} ->
+ ok
+ end
+ end,
+ process_flag(trap_exit, Bool),
+ ok;
+ undefined ->
+ ok
+ end.
+
+wait_for_version_negotiation(Pid, Timeout) ->
+ call(Pid, wait_for_version_negotiation, Timeout).
+
+open(Pid, File, Mode) ->
+ open(Pid, File, Mode, ?FILEOP_TIMEOUT).
+open(Pid, File, Mode, FileOpTimeout) ->
+ call(Pid, {open, false, File, Mode}, FileOpTimeout).
+
+opendir(Pid, Path) ->
+ opendir(Pid, Path, ?FILEOP_TIMEOUT).
+opendir(Pid, Path, FileOpTimeout) ->
+ call(Pid, {opendir, false, Path}, FileOpTimeout).
+
+close(Pid, Handle) ->
+ close(Pid, Handle, ?FILEOP_TIMEOUT).
+close(Pid, Handle, FileOpTimeout) ->
+ call(Pid, {close,false,Handle}, FileOpTimeout).
+
+readdir(Pid,Handle) ->
+ readdir(Pid,Handle, ?FILEOP_TIMEOUT).
+readdir(Pid,Handle, FileOpTimeout) ->
+ call(Pid, {readdir,false,Handle}, FileOpTimeout).
+
+pread(Pid, Handle, Offset, Len) ->
+ pread(Pid, Handle, Offset, Len, ?FILEOP_TIMEOUT).
+pread(Pid, Handle, Offset, Len, FileOpTimeout) ->
+ call(Pid, {pread,false,Handle, Offset, Len}, FileOpTimeout).
+
+read(Pid, Handle, Len) ->
+ read(Pid, Handle, Len, ?FILEOP_TIMEOUT).
+read(Pid, Handle, Len, FileOpTimeout) ->
+ call(Pid, {read,false,Handle, Len}, FileOpTimeout).
+
+%% TODO this ought to be a cast! Is so in all practial meaning
+%% even if it is obscure!
+apread(Pid, Handle, Offset, Len) ->
+ call(Pid, {pread,true,Handle, Offset, Len}, infinity).
+
+%% TODO this ought to be a cast!
+aread(Pid, Handle, Len) ->
+ call(Pid, {read,true,Handle, Len}, infinity).
+
+pwrite(Pid, Handle, Offset, Data) ->
+ pwrite(Pid, Handle, Offset, Data, ?FILEOP_TIMEOUT).
+pwrite(Pid, Handle, Offset, Data, FileOpTimeout) ->
+ call(Pid, {pwrite,false,Handle,Offset,Data}, FileOpTimeout).
+
+write(Pid, Handle, Data) ->
+ write(Pid, Handle, Data, ?FILEOP_TIMEOUT).
+write(Pid, Handle, Data, FileOpTimeout) ->
+ call(Pid, {write,false,Handle,Data}, FileOpTimeout).
+
+%% TODO this ought to be a cast! Is so in all practial meaning
+%% even if it is obscure!
+apwrite(Pid, Handle, Offset, Data) ->
+ call(Pid, {pwrite,true,Handle,Offset,Data}, infinity).
+
+%% TODO this ought to be a cast! Is so in all practial meaning
+%% even if it is obscure!
+awrite(Pid, Handle, Data) ->
+ call(Pid, {write,true,Handle,Data}, infinity).
+
+position(Pid, Handle, Pos) ->
+ position(Pid, Handle, Pos, ?FILEOP_TIMEOUT).
+position(Pid, Handle, Pos, FileOpTimeout) ->
+ call(Pid, {position, Handle, Pos}, FileOpTimeout).
+
+real_path(Pid, Path) ->
+ real_path(Pid, Path, ?FILEOP_TIMEOUT).
+real_path(Pid, Path, FileOpTimeout) ->
+ call(Pid, {real_path, false, Path}, FileOpTimeout).
+
+read_file_info(Pid, Name) ->
+ read_file_info(Pid, Name, ?FILEOP_TIMEOUT).
+read_file_info(Pid, Name, FileOpTimeout) ->
+ call(Pid, {read_file_info,false,Name}, FileOpTimeout).
+
+get_file_info(Pid, Handle) ->
+ get_file_info(Pid, Handle, ?FILEOP_TIMEOUT).
+get_file_info(Pid, Handle, FileOpTimeout) ->
+ call(Pid, {get_file_info,false,Handle}, FileOpTimeout).
+
+write_file_info(Pid, Name, Info) ->
+ write_file_info(Pid, Name, Info, ?FILEOP_TIMEOUT).
+write_file_info(Pid, Name, Info, FileOpTimeout) ->
+ call(Pid, {write_file_info,false,Name, Info}, FileOpTimeout).
+
+read_link_info(Pid, Name) ->
+ read_link_info(Pid, Name, ?FILEOP_TIMEOUT).
+read_link_info(Pid, Name, FileOpTimeout) ->
+ call(Pid, {read_link_info,false,Name}, FileOpTimeout).
+
+read_link(Pid, LinkName) ->
+ read_link(Pid, LinkName, ?FILEOP_TIMEOUT).
+read_link(Pid, LinkName, FileOpTimeout) ->
+ case call(Pid, {read_link,false,LinkName}, FileOpTimeout) of
+ {ok, [{Name, _Attrs}]} ->
+ {ok, Name};
+ ErrMsg ->
+ ErrMsg
+ end.
+
+make_symlink(Pid, Name, Target) ->
+ make_symlink(Pid, Name, Target, ?FILEOP_TIMEOUT).
+make_symlink(Pid, Name, Target, FileOpTimeout) ->
+ call(Pid, {make_symlink,false, Name, Target}, FileOpTimeout).
+
+rename(Pid, FromFile, ToFile) ->
+ rename(Pid, FromFile, ToFile, ?FILEOP_TIMEOUT).
+rename(Pid, FromFile, ToFile, FileOpTimeout) ->
+ call(Pid, {rename,false,FromFile, ToFile}, FileOpTimeout).
+
+delete(Pid, Name) ->
+ delete(Pid, Name, ?FILEOP_TIMEOUT).
+delete(Pid, Name, FileOpTimeout) ->
+ call(Pid, {delete,false,Name}, FileOpTimeout).
+
+make_dir(Pid, Name) ->
+ make_dir(Pid, Name, ?FILEOP_TIMEOUT).
+make_dir(Pid, Name, FileOpTimeout) ->
+ call(Pid, {make_dir,false,Name}, FileOpTimeout).
+
+del_dir(Pid, Name) ->
+ del_dir(Pid, Name, ?FILEOP_TIMEOUT).
+del_dir(Pid, Name, FileOpTimeout) ->
+ call(Pid, {del_dir,false,Name}, FileOpTimeout).
+
+%% TODO : send_window and recv_window - Really needed? Not documented!
+%% internal use maybe should be handled in other way!
+send_window(Pid) ->
+ send_window(Pid, ?FILEOP_TIMEOUT).
+send_window(Pid, FileOpTimeout) ->
+ call(Pid, send_window, FileOpTimeout).
+
+recv_window(Pid) ->
+ recv_window(Pid, ?FILEOP_TIMEOUT).
+recv_window(Pid, FileOpTimeout) ->
+ call(Pid, recv_window, FileOpTimeout).
+
+
+list_dir(Pid, Name) ->
+ list_dir(Pid, Name, ?FILEOP_TIMEOUT).
+
+list_dir(Pid, Name, FileOpTimeout) ->
+ case opendir(Pid, Name, FileOpTimeout) of
+ {ok,Handle} ->
+ Res = do_list_dir(Pid, Handle, FileOpTimeout, []),
+ close(Pid, Handle, FileOpTimeout),
+ case Res of
+ {ok, List} ->
+ NList = lists:foldl(fun({Nm, _Info},Acc) ->
+ [Nm|Acc] end,
+ [], List),
+ {ok,NList};
+ Error -> Error
+ end;
+ Error ->
+ Error
+ end.
+
+do_list_dir(Pid, Handle, FileOpTimeout, Acc) ->
+ case readdir(Pid, Handle, FileOpTimeout) of
+ {ok, []} ->
+ {ok, Acc};
+ {ok, Names} ->
+ do_list_dir(Pid, Handle, FileOpTimeout, Acc ++ Names);
+ eof ->
+ {ok, Acc};
+ Error ->
+ Error
+ end.
+
+
+read_file(Pid, Name) ->
+ read_file(Pid, Name, ?FILEOP_TIMEOUT).
+
+read_file(Pid, Name, FileOpTimeout) ->
+ case open(Pid, Name, [read, binary], FileOpTimeout) of
+ {ok, Handle} ->
+ {ok,{_WindowSz,PacketSz}} = recv_window(Pid, FileOpTimeout),
+ Res = read_file_loop(Pid, Handle, PacketSz, FileOpTimeout, []),
+ close(Pid, Handle),
+ Res;
+ Error ->
+ Error
+ end.
+
+read_file_loop(Pid, Handle, PacketSz, FileOpTimeout, Acc) ->
+ case read(Pid, Handle, PacketSz, FileOpTimeout) of
+ {ok, Data} ->
+ read_file_loop(Pid, Handle, PacketSz, FileOpTimeout, [Data|Acc]);
+ eof ->
+ {ok, list_to_binary(lists:reverse(Acc))};
+ Error ->
+ Error
+ end.
+
+write_file(Pid, Name, List) ->
+ write_file(Pid, Name, List, ?FILEOP_TIMEOUT).
+
+write_file(Pid, Name, List, FileOpTimeout) when is_list(List) ->
+ write_file(Pid, Name, list_to_binary(List), FileOpTimeout);
+write_file(Pid, Name, Bin, FileOpTimeout) ->
+ case open(Pid, Name, [write, binary], FileOpTimeout) of
+ {ok, Handle} ->
+ {ok,{_Window,Packet}} = send_window(Pid, FileOpTimeout),
+ Res = write_file_loop(Pid, Handle, 0, Bin, size(Bin), Packet,
+ FileOpTimeout),
+ close(Pid, Handle, FileOpTimeout),
+ Res;
+ Error ->
+ Error
+ end.
+
+write_file_loop(_Pid, _Handle, _Pos, _Bin, 0, _PacketSz,_FileOpTimeout) ->
+ ok;
+write_file_loop(Pid, Handle, Pos, Bin, Remain, PacketSz, FileOpTimeout) ->
+ if Remain >= PacketSz ->
+ <<_:Pos/binary, Data:PacketSz/binary, _/binary>> = Bin,
+ case write(Pid, Handle, Data, FileOpTimeout) of
+ ok ->
+ write_file_loop(Pid, Handle,
+ Pos+PacketSz, Bin, Remain-PacketSz,
+ PacketSz, FileOpTimeout);
+ Error ->
+ Error
+ end;
+ true ->
+ <<_:Pos/binary, Data/binary>> = Bin,
+ write(Pid, Handle, Data, FileOpTimeout)
+ end.
+
+%%====================================================================
+%% SSh channel callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State}
+%%
+%% Description:
+%%--------------------------------------------------------------------
+init([Cm, ChannelId, Timeout]) ->
+ erlang:monitor(process, Cm),
+ case ssh_connection:subsystem(Cm, ChannelId, "sftp", Timeout) of
+ success ->
+ Xf = #ssh_xfer{cm = Cm,
+ channel = ChannelId},
+ {ok, #state{xf = Xf,
+ req_id = 0,
+ rep_buf = <<>>,
+ inf = new_inf()}};
+ failure ->
+ {stop, {error, "server failed to start sftp subsystem"}};
+ Error ->
+ {stop, Error}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: handle_call/3
+%% Description: Handling call messages
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_call({{timeout, infinity}, wait_for_version_negotiation}, From,
+ #state{xf = #ssh_xfer{vsn = undefined} = Xf} = State) ->
+ {noreply, State#state{xf = Xf#ssh_xfer{vsn = From}}};
+
+handle_call({{timeout, Timeout}, wait_for_version_negotiation}, From,
+ #state{xf = #ssh_xfer{vsn = undefined} = Xf} = State) ->
+ timer:send_after(Timeout, {timeout, undefined, From}),
+ {noreply, State#state{xf = Xf#ssh_xfer{vsn = From}}};
+
+handle_call({_, wait_for_version_negotiation}, _, State) ->
+ {reply, ok, State};
+
+handle_call({{timeout, infinity}, Msg}, From, State) ->
+ do_handle_call(Msg, From, State);
+handle_call({{timeout, Timeout}, Msg}, From, #state{req_id = Id} = State) ->
+ timer:send_after(Timeout, {timeout, Id, From}),
+ do_handle_call(Msg, From, State).
+
+do_handle_call({open, Async,FileName,Mode}, From, #state{xf = XF} = State) ->
+ {Access,Flags,Attrs} = open_mode(XF#ssh_xfer.vsn, Mode),
+ ReqID = State#state.req_id,
+ ssh_xfer:open(XF, ReqID, FileName, Access, Flags, Attrs),
+ case Async of
+ true ->
+ {reply, {async,ReqID},
+ update_request_info(ReqID, State,
+ fun({ok,Handle},State1) ->
+ open2(ReqID,FileName,Handle,Mode,Async,
+ From,State1);
+ (Rep,State1) ->
+ async_reply(ReqID, Rep, From, State1)
+ end)};
+ false ->
+ {noreply,
+ update_request_info(ReqID, State,
+ fun({ok,Handle},State1) ->
+ open2(ReqID,FileName,Handle,Mode,Async,
+ From,State1);
+ (Rep,State1) ->
+ sync_reply(Rep, From, State1)
+ end)}
+ end;
+
+do_handle_call({opendir,Async,Path}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:opendir(?XF(State), ReqID, Path),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({readdir,Async,Handle}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:readdir(?XF(State), ReqID, Handle),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({close,_Async,Handle}, From, State) ->
+ %% wait until all operations on handle are done
+ case get_size(Handle, State) of
+ undefined ->
+ ReqID = State#state.req_id,
+ ssh_xfer:close(?XF(State), ReqID, Handle),
+ make_reply_post(ReqID, false, From, State,
+ fun(Rep, State1) ->
+ {Rep, erase_handle(Handle, State1)}
+ end);
+ _ ->
+ case lseek_position(Handle, cur, State) of
+ {ok,_} ->
+ ReqID = State#state.req_id,
+ ssh_xfer:close(?XF(State), ReqID, Handle),
+ make_reply_post(ReqID, false, From, State,
+ fun(Rep, State1) ->
+ {Rep, erase_handle(Handle, State1)}
+ end);
+ Error ->
+ {reply, Error, State}
+ end
+ end;
+
+do_handle_call({pread,Async,Handle,At,Length}, From, State) ->
+ case lseek_position(Handle, At, State) of
+ {ok,Offset} ->
+ ReqID = State#state.req_id,
+ ssh_xfer:read(?XF(State),ReqID,Handle,Offset,Length),
+ %% To get multiple async read to work we must update the offset
+ %% before the operation begins
+ State1 = update_offset(Handle, Offset+Length, State),
+ make_reply_post(ReqID,Async,From,State1,
+ fun({ok,Data}, State2) ->
+ case get_mode(Handle, State2) of
+ binary -> {{ok,Data}, State2};
+ text ->
+ {{ok,binary_to_list(Data)}, State2}
+ end;
+ (Rep, State2) ->
+ {Rep, State2}
+ end);
+ Error ->
+ {reply, Error, State}
+ end;
+
+do_handle_call({read,Async,Handle,Length}, From, State) ->
+ case lseek_position(Handle, cur, State) of
+ {ok,Offset} ->
+ ReqID = State#state.req_id,
+ ssh_xfer:read(?XF(State),ReqID,Handle,Offset,Length),
+ %% To get multiple async read to work we must update the offset
+ %% before the operation begins
+ State1 = update_offset(Handle, Offset+Length, State),
+ make_reply_post(ReqID,Async,From,State1,
+ fun({ok,Data}, State2) ->
+ case get_mode(Handle, State2) of
+ binary -> {{ok,Data}, State2};
+ text ->
+ {{ok,binary_to_list(Data)}, State2}
+ end;
+ (Rep, State2) -> {Rep, State2}
+ end);
+ Error ->
+ {reply, Error, State}
+ end;
+
+do_handle_call({pwrite,Async,Handle,At,Data0}, From, State) ->
+ case lseek_position(Handle, At, State) of
+ {ok,Offset} ->
+ Data = if
+ is_binary(Data0) ->
+ Data0;
+ is_list(Data0) ->
+ list_to_binary(Data0)
+ end,
+ ReqID = State#state.req_id,
+ Size = size(Data),
+ ssh_xfer:write(?XF(State),ReqID,Handle,Offset,Data),
+ State1 = update_size(Handle, Offset+Size, State),
+ make_reply(ReqID, Async, From, State1);
+ Error ->
+ {reply, Error, State}
+ end;
+
+do_handle_call({write,Async,Handle,Data0}, From, State) ->
+ case lseek_position(Handle, cur, State) of
+ {ok,Offset} ->
+ Data = if
+ is_binary(Data0) ->
+ Data0;
+ is_list(Data0) ->
+ list_to_binary(Data0)
+ end,
+ ReqID = State#state.req_id,
+ Size = size(Data),
+ ssh_xfer:write(?XF(State),ReqID,Handle,Offset,Data),
+ State1 = update_offset(Handle, Offset+Size, State),
+ make_reply(ReqID, Async, From, State1);
+ Error ->
+ {reply, Error, State}
+ end;
+
+do_handle_call({position,Handle,At}, _From, State) ->
+ %% We could make this auto sync when all request to Handle is done?
+ case lseek_position(Handle, At, State) of
+ {ok,Offset} ->
+ {reply, {ok, Offset}, update_offset(Handle, Offset, State)};
+ Error ->
+ {reply, Error, State}
+ end;
+
+do_handle_call({rename,Async,FromFile,ToFile}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:rename(?XF(State),ReqID,FromFile,ToFile,[overwrite]),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({delete,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:remove(?XF(State), ReqID, Name),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({make_dir,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:mkdir(?XF(State), ReqID, Name,
+ #ssh_xfer_attr{ type = directory }),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({del_dir,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:rmdir(?XF(State), ReqID, Name),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({real_path,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:realpath(?XF(State), ReqID, Name),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({read_file_info,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:stat(?XF(State), ReqID, Name, all),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({get_file_info,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:fstat(?XF(State), ReqID, Name, all),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({read_link_info,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:lstat(?XF(State), ReqID, Name, all),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({read_link,Async,Name}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:readlink(?XF(State), ReqID, Name),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({make_symlink, Async, Path, TargetPath}, From, State) ->
+ ReqID = State#state.req_id,
+ ssh_xfer:symlink(?XF(State), ReqID, Path, TargetPath),
+ make_reply(ReqID, Async, From, State);
+
+do_handle_call({write_file_info,Async,Name,Info}, From, State) ->
+ ReqID = State#state.req_id,
+ A = info_to_attr(Info),
+ ssh_xfer:setstat(?XF(State), ReqID, Name, A),
+ make_reply(ReqID, Async, From, State);
+
+%% TODO: Do we really want this format? Function send_window
+%% is not documented and seems to be used only inernaly!
+%% It is backwards compatible for now.
+do_handle_call(send_window, _From, State) ->
+ XF = State#state.xf,
+ [{send_window,{{win_size, Size0},{packet_size, Size1}}}] =
+ ssh:channel_info(XF#ssh_xfer.cm, XF#ssh_xfer.channel, [send_window]),
+ {reply, {ok, {Size0, Size1}}, State};
+
+%% TODO: Do we really want this format? Function recv_window
+%% is not documented and seems to be used only inernaly!
+%% It is backwards compatible for now.
+do_handle_call(recv_window, _From, State) ->
+ XF = State#state.xf,
+ [{recv_window,{{win_size, Size0},{packet_size, Size1}}}] =
+ ssh:channel_info(XF#ssh_xfer.cm, XF#ssh_xfer.channel, [recv_window]),
+ {reply, {ok, {Size0, Size1}}, State};
+
+%% Backwards compatible
+do_handle_call(stop, _From, State) ->
+ {stop, shutdown, ok, State};
+
+do_handle_call(Call, _From, State) ->
+ {reply, {error, bad_call, Call, State}, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles channel messages
+%%--------------------------------------------------------------------
+handle_ssh_msg({ssh_cm, _ConnectionManager,
+ {data, _ChannelId, 0, Data}}, #state{rep_buf = Data0} =
+ State0) ->
+ State = handle_reply(State0, <<Data0/binary,Data/binary>>),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _ConnectionManager,
+ {data, _ChannelId, 1, Data}}, State) ->
+ error_logger:format("ssh: STDERR: ~s\n", [binary_to_list(Data)]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) ->
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
+ %% Ignore signals according to RFC 4254 section 6.9.
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}},
+ State0) ->
+ State = reply_all(State0, {error, Error}),
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State0) ->
+ State = reply_all(State0, {error, {exit_status, Status}}),
+ {stop, ChannelId, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles channel messages
+%%--------------------------------------------------------------------
+handle_msg({ssh_channel_up, _, _}, #state{xf = Xf} = State) ->
+ ssh_xfer:protocol_version_request(Xf),
+ {ok, State};
+
+%% Version negotiation timed out
+handle_msg({timeout, undefined, From},
+ #state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
+ ssh_channel:reply(From, {error, timeout}),
+ {stop, ChannelId, State};
+
+handle_msg({timeout, Id, From}, #state{req_list = ReqList0} = State) ->
+ case lists:keysearch(Id, 1, ReqList0) of
+ false ->
+ {ok, State};
+ _ ->
+ ReqList = lists:keydelete(Id, 1, ReqList0),
+ ssh_channel:reply(From, {error, timeout}),
+ {ok, State#state{req_list = ReqList}}
+ end;
+
+%% Connection manager goes down
+handle_msg({'DOWN', _Ref, _Type, _Process, _},
+ #state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
+ {stop, ChannelId, State};
+
+%% Stopped by user
+handle_msg({'EXIT', _, ssh_sftp_stop_channel},
+ #state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
+ {stop, ChannelId, State};
+
+handle_msg(_, State) ->
+ {ok, State}.
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: Called when the channel process is terminated
+%%--------------------------------------------------------------------
+%% Backwards compatible
+terminate(shutdown, #state{xf = #ssh_xfer{cm = Cm}} = State) ->
+ reply_all(State, {error, closed}),
+ ssh:close(Cm);
+
+terminate(_Reason, State) ->
+ reply_all(State, {error, closed}).
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+call(Pid, Msg, TimeOut) ->
+ ssh_channel:call(Pid, {{timeout, TimeOut}, Msg}, infinity).
+
+handle_reply(State, <<?UINT32(Len),Reply:Len/binary,Rest/binary>>) ->
+ do_handle_reply(State, Reply, Rest);
+handle_reply(State, Data) ->
+ State#state{rep_buf = Data}.
+
+do_handle_reply(#state{xf = Xf} = State,
+ <<?SSH_FXP_VERSION, ?UINT32(Version), BinExt/binary>>, Rest) ->
+ Ext = ssh_xfer:decode_ext(BinExt),
+ case Xf#ssh_xfer.vsn of
+ undefined ->
+ ok;
+ From ->
+ ssh_channel:reply(From, ok)
+ end,
+ State#state{xf = Xf#ssh_xfer{vsn = Version, ext = Ext}, rep_buf = Rest};
+
+do_handle_reply(State0, Data, Rest) ->
+ case catch ssh_xfer:xf_reply(?XF(State0), Data) of
+ {'EXIT', _Reason} ->
+ handle_reply(State0, Rest);
+ XfReply ->
+ State = handle_req_reply(State0, XfReply),
+ handle_reply(State, Rest)
+ end.
+
+handle_req_reply(State0, {_, ReqID, _} = XfReply) ->
+ case lists:keysearch(ReqID, 1, State0#state.req_list) of
+ false ->
+ State0;
+ {value,{_,Fun}} ->
+ List = lists:keydelete(ReqID, 1, State0#state.req_list),
+ State1 = State0#state { req_list = List },
+ case catch Fun(xreply(XfReply),State1) of
+ {'EXIT', _} ->
+ State1;
+ State ->
+ State
+ end
+ end.
+
+xreply({handle,_,H}) -> {ok, H};
+xreply({data,_,Data}) -> {ok, Data};
+xreply({name,_,Names}) -> {ok, Names};
+xreply({attrs, _, A}) -> {ok, attr_to_info(A)};
+xreply({extended_reply,_,X}) -> {ok, X};
+xreply({status,_,{ok, _Err, _Lang, _Rep}}) -> ok;
+xreply({status,_,{eof, _Err, _Lang, _Rep}}) -> eof;
+xreply({status,_,{Stat, _Err, _Lang, _Rep}}) -> {error, Stat};
+xreply({Code, _, Reply}) -> {Code, Reply}.
+
+update_request_info(ReqID, State, Fun) ->
+ List = [{ReqID,Fun} | State#state.req_list],
+ ID = (State#state.req_id + 1) band 16#ffffffff,
+ State#state { req_list = List, req_id = ID }.
+
+async_reply(ReqID, Reply, _From={To,_}, State) ->
+ To ! {async_reply, ReqID, Reply},
+ State.
+
+sync_reply(Reply, From, State) ->
+ catch (ssh_channel:reply(From, Reply)),
+ State.
+
+open2(OrigReqID,FileName,Handle,Mode,Async,From,State) ->
+ I0 = State#state.inf,
+ FileMode = case lists:member(binary, Mode) orelse lists:member(raw, Mode) of
+ true -> binary;
+ false -> text
+ end,
+ I1 = add_new_handle(Handle, FileMode, I0),
+ State0 = State#state{inf = I1},
+ ReqID = State0#state.req_id,
+ ssh_xfer:stat(State0#state.xf, ReqID, FileName, [size]),
+ case Async of
+ true ->
+ update_request_info(ReqID, State0,
+ fun({ok,FI},State1) ->
+ Size = FI#file_info.size,
+ State2 = if is_integer(Size) ->
+ put_size(Handle, Size, State1);
+ true ->
+ State1
+ end,
+ async_reply(OrigReqID, {ok,Handle}, From, State2);
+ (_, State1) ->
+ async_reply(OrigReqID, {ok,Handle}, From, State1)
+ end);
+ false ->
+ update_request_info(ReqID, State0,
+ fun({ok,FI},State1) ->
+ Size = FI#file_info.size,
+ State2 = if is_integer(Size) ->
+ put_size(Handle, Size, State1);
+ true ->
+ State1
+ end,
+ sync_reply({ok,Handle}, From, State2);
+ (_, State1) ->
+ sync_reply({ok,Handle}, From, State1)
+ end)
+ end.
+
+reply_all(State, Reply) ->
+ List = State#state.req_list,
+ lists:foreach(fun({_ReqID,Fun}) ->
+ catch Fun(Reply,State)
+ end, List),
+ State#state {req_list = []}.
+
+make_reply(ReqID, true, From, State) ->
+ {reply, {async, ReqID},
+ update_request_info(ReqID, State,
+ fun(Reply,State1) ->
+ async_reply(ReqID,Reply,From,State1)
+ end)};
+
+make_reply(ReqID, false, From, State) ->
+ {noreply,
+ update_request_info(ReqID, State,
+ fun(Reply,State1) ->
+ sync_reply(Reply, From, State1)
+ end)}.
+
+make_reply_post(ReqID, true, From, State, PostFun) ->
+ {reply, {async, ReqID},
+ update_request_info(ReqID, State,
+ fun(Reply,State1) ->
+ case catch PostFun(Reply, State1) of
+ {'EXIT',_} ->
+ async_reply(ReqID,Reply, From, State1);
+ {Reply1, State2} ->
+ async_reply(ReqID,Reply1, From, State2)
+ end
+ end)};
+
+make_reply_post(ReqID, false, From, State, PostFun) ->
+ {noreply,
+ update_request_info(ReqID, State,
+ fun(Reply,State1) ->
+ case catch PostFun(Reply, State1) of
+ {'EXIT',_} ->
+ sync_reply(Reply, From, State1);
+ {Reply1, State2} ->
+ sync_reply(Reply1, From, State2)
+ end
+ end)}.
+
+%% convert: file_info -> ssh_xfer_attr
+info_to_attr(I) when is_record(I, file_info) ->
+ #ssh_xfer_attr { permissions = I#file_info.mode,
+ size = I#file_info.size,
+ type = I#file_info.type,
+ owner = I#file_info.uid,
+ group = I#file_info.gid,
+ atime = datetime_to_unix(I#file_info.atime),
+ mtime = datetime_to_unix(I#file_info.mtime),
+ createtime = datetime_to_unix(I#file_info.ctime)}.
+
+%% convert: ssh_xfer_attr -> file_info
+attr_to_info(A) when is_record(A, ssh_xfer_attr) ->
+ #file_info{
+ size = A#ssh_xfer_attr.size,
+ type = A#ssh_xfer_attr.type,
+ access = read_write, %% FIXME: read/write/read_write/none
+ atime = unix_to_datetime(A#ssh_xfer_attr.atime),
+ mtime = unix_to_datetime(A#ssh_xfer_attr.mtime),
+ ctime = unix_to_datetime(A#ssh_xfer_attr.createtime),
+ mode = A#ssh_xfer_attr.permissions,
+ links = 1,
+ major_device = 0,
+ minor_device = 0,
+ inode = 0,
+ uid = A#ssh_xfer_attr.owner,
+ gid = A#ssh_xfer_attr.group}.
+
+
+%% Added workaround for sftp timestam problem. (Timestamps should be
+%% in UTC but they where not) . The workaround uses a deprecated
+%% function i calandar. This will work as expected most of the time
+%% but has problems for the same reason as
+%% calendar:local_time_to_universal_time/1. We consider it better that
+%% the timestamps work as expected most of the time instead of none of
+%% the time. Hopfully the file-api will be updated so that we can
+%% solve this problem in a better way in the future.
+
+unix_to_datetime(undefined) ->
+ undefined;
+unix_to_datetime(UTCSecs) ->
+ UTCDateTime =
+ calendar:gregorian_seconds_to_datetime(UTCSecs + 62167219200),
+ erlang:universaltime_to_localtime(UTCDateTime).
+
+datetime_to_unix(undefined) ->
+ undefined;
+datetime_to_unix(LocalDateTime) ->
+ UTCDateTime = erlang:localtime_to_universaltime(LocalDateTime),
+ calendar:datetime_to_gregorian_seconds(UTCDateTime) - 62167219200.
+
+
+open_mode(Vsn,Modes) when Vsn >= 5 ->
+ open_mode5(Modes);
+open_mode(_Vsn, Modes) ->
+ open_mode3(Modes).
+
+open_mode5(Modes) ->
+ A = #ssh_xfer_attr{type = regular},
+ {Fl, Ac} = case {lists:member(write, Modes),
+ lists:member(read, Modes),
+ lists:member(append, Modes)} of
+ {_, _, true} ->
+ {[append_data],
+ [read_attributes,
+ append_data, write_attributes]};
+ {true, false, false} ->
+ {[create_truncate],
+ [write_data, write_attributes]};
+ {true, true, _} ->
+ {[open_or_create],
+ [read_data, read_attributes,
+ write_data, write_attributes]};
+ {false, true, _} ->
+ {[open_existing],
+ [read_data, read_attributes]}
+ end,
+ {Ac, Fl, A}.
+
+open_mode3(Modes) ->
+ A = #ssh_xfer_attr{type = regular},
+ Fl = case {lists:member(write, Modes),
+ lists:member(read, Modes),
+ lists:member(append, Modes)} of
+ {_, _, true} ->
+ [append];
+ {true, false, false} ->
+ [write, creat, trunc];
+ {true, true, _} ->
+ [read, write];
+ {false, true, _} ->
+ [read]
+ end,
+ {[], Fl, A}.
+
+%% accessors for inf dict
+new_inf() -> dict:new().
+
+add_new_handle(Handle, FileMode, Inf) ->
+ dict:store(Handle, #fileinf{offset=0, size=0, mode=FileMode}, Inf).
+
+update_size(Handle, NewSize, State) ->
+ OldSize = get_size(Handle, State),
+ if NewSize > OldSize ->
+ put_size(Handle, NewSize, State);
+ true ->
+ State
+ end.
+
+%% set_offset(Handle, NewOffset) ->
+%% put({offset,Handle}, NewOffset).
+
+update_offset(Handle, NewOffset, State0) ->
+ State1 = put_offset(Handle, NewOffset, State0),
+ update_size(Handle, NewOffset, State1).
+
+%% access size and offset for handle
+put_size(Handle, Size, State) ->
+ Inf0 = State#state.inf,
+ case dict:find(Handle, Inf0) of
+ {ok, FI} ->
+ State#state{inf=dict:store(Handle, FI#fileinf{size=Size}, Inf0)};
+ _ ->
+ State#state{inf=dict:store(Handle, #fileinf{size=Size,offset=0},
+ Inf0)}
+ end.
+
+put_offset(Handle, Offset, State) ->
+ Inf0 = State#state.inf,
+ case dict:find(Handle, Inf0) of
+ {ok, FI} ->
+ State#state{inf=dict:store(Handle, FI#fileinf{offset=Offset},
+ Inf0)};
+ _ ->
+ State#state{inf=dict:store(Handle, #fileinf{size=Offset,
+ offset=Offset}, Inf0)}
+ end.
+
+get_size(Handle, State) ->
+ case dict:find(Handle, State#state.inf) of
+ {ok, FI} ->
+ FI#fileinf.size;
+ _ ->
+ undefined
+ end.
+
+%% get_offset(Handle, State) ->
+%% {ok, FI} = dict:find(Handle, State#state.inf),
+%% FI#fileinf.offset.
+
+get_mode(Handle, State) ->
+ case dict:find(Handle, State#state.inf) of
+ {ok, FI} ->
+ FI#fileinf.mode;
+ _ ->
+ undefined
+ end.
+
+erase_handle(Handle, State) ->
+ FI = dict:erase(Handle, State#state.inf),
+ State#state{inf = FI}.
+
+%%
+%% Caluclate a integer offset
+%%
+lseek_position(Handle, Pos, State) ->
+ case dict:find(Handle, State#state.inf) of
+ {ok, #fileinf{offset=O, size=S}} ->
+ lseek_pos(Pos, O, S);
+ _ ->
+ {error, einval}
+ end.
+
+lseek_pos(_Pos, undefined, _) ->
+ {error, einval};
+lseek_pos(Pos, _CurOffset, _CurSize)
+ when is_integer(Pos) andalso 0 =< Pos andalso Pos < ?SSH_FILEXFER_LARGEFILESIZE ->
+ {ok,Pos};
+lseek_pos(bof, _CurOffset, _CurSize) ->
+ {ok,0};
+lseek_pos(cur, CurOffset, _CurSize) ->
+ {ok,CurOffset};
+lseek_pos(eof, _CurOffset, CurSize) ->
+ {ok,CurSize};
+lseek_pos({bof, Offset}, _CurOffset, _CurSize)
+ when is_integer(Offset) andalso 0 =< Offset andalso Offset < ?SSH_FILEXFER_LARGEFILESIZE ->
+ {ok, Offset};
+lseek_pos({cur, Offset}, CurOffset, _CurSize)
+ when is_integer(Offset) andalso -(?SSH_FILEXFER_LARGEFILESIZE) =< Offset andalso
+ Offset < ?SSH_FILEXFER_LARGEFILESIZE ->
+ NewOffset = CurOffset + Offset,
+ if NewOffset < 0 ->
+ {ok, 0};
+ true ->
+ {ok, NewOffset}
+ end;
+lseek_pos({eof, Offset}, _CurOffset, CurSize)
+ when is_integer(Offset) andalso -(?SSH_FILEXFER_LARGEFILESIZE) =< Offset andalso
+ Offset < ?SSH_FILEXFER_LARGEFILESIZE ->
+ NewOffset = CurSize + Offset,
+ if NewOffset < 0 ->
+ {ok, 0};
+ true ->
+ {ok, NewOffset}
+ end;
+lseek_pos(_, _, _) ->
+ {error, einval}.
+
+
+%%%%%% Deprecated %%%%
+connect(Cm) when is_pid(Cm) ->
+ connect(Cm, []);
+connect(Host) when is_list(Host) ->
+ connect(Host, []).
+connect(Cm, Opts) when is_pid(Cm) ->
+ Timeout = proplists:get_value(timeout, Opts, infinity),
+ case ssh_xfer:attach(Cm, []) of
+ {ok, ChannelId, Cm} ->
+ ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm, ChannelId,
+ Timeout]);
+ Error ->
+ Error
+ end;
+connect(Host, Opts) ->
+ connect(Host, 22, Opts).
+connect(Host, Port, Opts) ->
+ Timeout = proplists:get_value(timeout, Opts, infinity),
+ case ssh_xfer:connect(Host, Port, proplists:delete(timeout, Opts)) of
+ {ok, ChannelId, Cm} ->
+ ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm,
+ ChannelId, Timeout]);
+ Error ->
+ Error
+ end.
+
+
+stop(Pid) ->
+ call(Pid, stop, infinity).
+
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
new file mode 100644
index 0000000000..10b8ede1e4
--- /dev/null
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -0,0 +1,932 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: SFTP server daemon
+
+-module(ssh_sftpd).
+
+%%-behaviour(gen_server).
+-behaviour(ssh_channel).
+
+-include_lib("kernel/include/file.hrl").
+
+-include("ssh.hrl").
+-include("ssh_xfer.hrl").
+
+%%--------------------------------------------------------------------
+%% External exports
+-export([subsystem_spec/1,
+ listen/1, listen/2, listen/3, stop/1]).
+
+-export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2, code_change/3]).
+
+-record(state, {
+ xf, % [{channel,ssh_xfer states}...]
+ cwd, % current dir (on first connect)
+ root, % root dir
+ remote_channel, % remote channel
+ pending, % binary()
+ file_handler, % atom() - callback module
+ file_state, % state for the file callback module
+ max_files, % integer >= 0 max no files sent during READDIR
+ handles % list of open handles
+ %% handle is either {<int>, directory, {Path, unread|eof}} or
+ %% {<int>, file, {Path, IoDevice}}
+ }).
+
+%%====================================================================
+%% API
+%%====================================================================
+subsystem_spec(Options) ->
+ {"sftp", {?MODULE, Options}}.
+
+%%% DEPRECATED START %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%--------------------------------------------------------------------
+%% Function: listen() -> Pid | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+listen(Port) ->
+ listen(any, Port, []).
+listen(Port, Options) ->
+ listen(any, Port, Options).
+listen(Addr, Port, Options) ->
+ SubSystems = [subsystem_spec(Options)],
+ ssh:daemon(Addr, Port, [{subsystems, SubSystems} |Options]).
+
+%%--------------------------------------------------------------------
+%% Function: stop(Pid) -> ok
+%% Description: Stops the listener
+%%--------------------------------------------------------------------
+stop(Pid) ->
+ ssh_cli:stop(Pid).
+
+
+%%% DEPRECATED END %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%====================================================================
+%% subsystem callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init(Options) ->
+ {FileMod, FS0} = case proplists:get_value(file_handler, Options,
+ {ssh_sftpd_file,[]}) of
+ {F, S} ->
+ {F, S};
+ F ->
+ {F, []}
+ end,
+
+ {{ok, Default}, FS1} = FileMod:get_cwd(FS0),
+ CWD = proplists:get_value(cwd, Options, Default),
+
+ Root0 = proplists:get_value(root, Options, ""),
+
+ %% Get the root of the file system (symlinks must be followed,
+ %% otherwise the realpath call won't work). But since symbolic links
+ %% isn't supported on all plattforms we have to use the root property
+ %% supplied by the user.
+ {Root, State} =
+ case resolve_symlinks(Root0,
+ #state{root = Root0,
+ file_handler = FileMod,
+ file_state = FS1}) of
+ {{ok, Root1}, State0} ->
+ {Root1, State0};
+ {{error, _}, State0} ->
+ {Root0, State0}
+ end,
+ MaxLength = proplists:get_value(max_files, Options, 0),
+
+ Vsn = proplists:get_value(vsn, Options, 5),
+
+ {ok, State#state{cwd = CWD, root = Root, max_files = MaxLength,
+ handles = [], pending = <<>>,
+ xf = #ssh_xfer{vsn = Vsn, ext = []}}}.
+
+
+%%--------------------------------------------------------------------
+%% Function: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description:
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+
+%%--------------------------------------------------------------------
+%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles channel messages
+%%--------------------------------------------------------------------
+handle_ssh_msg({ssh_cm, _ConnectionManager,
+ {data, _ChannelId, Type, Data}}, State) ->
+ State1 = handle_data(Type, Data, State),
+ {ok, State1};
+
+handle_ssh_msg({ssh_cm, _, {eof, ChannelId}}, State) ->
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
+ %% Ignore signals according to RFC 4254 section 6.9.
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}}, State) ->
+ Report = io_lib:format("Connection closed by peer ~n Error ~p~n",
+ [Error]),
+ error_logger:error_report(Report),
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, 0}}, State) ->
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State) ->
+
+ Report = io_lib:format("Connection closed by peer ~n Status ~p~n",
+ [Status]),
+ error_logger:error_report(Report),
+ {stop, ChannelId, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles other messages
+%%--------------------------------------------------------------------
+handle_msg({ssh_channel_up, ChannelId, ConnectionManager},
+ #state{xf =Xf} = State) ->
+ {ok, State#state{xf = Xf#ssh_xfer{cm = ConnectionManager,
+ channel = ChannelId}}}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(_, #state{handles=Handles, file_handler=FileMod, file_state=FS}) ->
+ CloseFun = fun({_, file, {_, Fd}}, FS0) ->
+ {_Res, FS1} = FileMod:close(Fd, FS0),
+ FS1;
+ (_, FS0) ->
+ FS0
+ end,
+ lists:foldl(CloseFun, FS, Handles),
+ ok.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+handle_data(0, <<?UINT32(Len), Msg:Len/binary, Rest/binary>>,
+ State = #state{pending = <<>>}) ->
+ <<Op, ?UINT32(ReqId), Data/binary>> = Msg,
+ NewState = handle_op(Op, ReqId, Data, State),
+ case Rest of
+ <<>> ->
+ NewState;
+ _ ->
+ handle_data(0, Rest, NewState)
+ end;
+
+handle_data(0, Data, State = #state{pending = <<>>}) ->
+ State#state{pending = Data};
+
+handle_data(Type, Data, State = #state{pending = Pending}) ->
+ handle_data(Type, <<Pending/binary, Data/binary>>,
+ State#state{pending = <<>>}).
+
+handle_op(?SSH_FXP_INIT, Version, B, State) when is_binary(B) ->
+ XF = State#state.xf,
+ Vsn = lists:min([XF#ssh_xfer.vsn, Version]),
+ XF1 = XF#ssh_xfer{vsn = Vsn},
+ ssh_xfer:xf_send_reply(XF1, ?SSH_FXP_VERSION, <<?UINT32(Vsn)>>),
+ State#state{xf = XF1};
+handle_op(?SSH_FXP_REALPATH, ReqId,
+ <<?UINT32(Rlen), RPath:Rlen/binary>>,
+ State0) ->
+ RelPath0 = binary_to_list(RPath),
+ RelPath = relate_file_name(RelPath0, State0, _Canonicalize=false),
+ {Res, State} = resolve_symlinks(RelPath, State0),
+ case Res of
+ {ok, AbsPath} ->
+ NewAbsPath = chroot_filename(AbsPath, State),
+ ?dbg(true, "handle_op ?SSH_FXP_REALPATH: RelPath=~p AbsPath=~p\n",
+ [RelPath, NewAbsPath]),
+ XF = State#state.xf,
+ Attr = #ssh_xfer_attr{type=directory},
+ ssh_xfer:xf_send_name(XF, ReqId, NewAbsPath, Attr),
+ State;
+ {error, _} = Error ->
+ send_status(Error, ReqId, State)
+ end;
+handle_op(?SSH_FXP_OPENDIR, ReqId,
+ <<?UINT32(RLen), RPath:RLen/binary>>,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ RelPath = binary_to_list(RPath),
+ AbsPath = relate_file_name(RelPath, State0),
+
+ XF = State0#state.xf,
+ {IsDir, FS1} = FileMod:is_dir(AbsPath, FS0),
+ State1 = State0#state{file_state = FS1},
+ case IsDir of
+ false ->
+ ssh_xfer:xf_send_status(XF, ReqId, ?SSH_FX_NOT_A_DIRECTORY,
+ "Not a directory"),
+ State1;
+ true ->
+ add_handle(State1, XF, ReqId, directory, {RelPath,unread})
+ end;
+handle_op(?SSH_FXP_READDIR, ReqId,
+ <<?UINT32(HLen), BinHandle:HLen/binary>>,
+ State) ->
+ XF = State#state.xf,
+ case get_handle(State#state.handles, BinHandle) of
+ {_Handle, directory, {_RelPath, eof}} ->
+ ssh_xfer:xf_send_status(XF, ReqId, ?SSH_FX_EOF),
+ State;
+ {Handle, directory, {RelPath, Status}} ->
+ read_dir(State, XF, ReqId, Handle, RelPath, Status);
+ _ ->
+ ssh_xfer:xf_send_status(XF, ReqId, ?SSH_FX_INVALID_HANDLE),
+ State
+ end;
+handle_op(?SSH_FXP_CLOSE, ReqId,
+ <<?UINT32(HLen), BinHandle:HLen/binary>>,
+ State = #state{handles = Handles, xf = XF,
+ file_handler = FileMod, file_state = FS0}) ->
+ case get_handle(Handles, BinHandle) of
+ {Handle, Type, T} ->
+ FS1 = case Type of
+ file ->
+ close_our_file(T, FileMod, FS0);
+ _ ->
+ FS0
+ end,
+ ssh_xfer:xf_send_status(XF, ReqId, ?SSH_FX_OK),
+ State#state{handles = lists:keydelete(Handle, 1, Handles),
+ file_state = FS1};
+ _ ->
+ ssh_xfer:xf_send_status(XF, ReqId, ?SSH_FX_INVALID_HANDLE),
+ State
+ end;
+handle_op(?SSH_FXP_LSTAT, ReqId, Data, State) ->
+ stat((State#state.xf)#ssh_xfer.vsn, ReqId, Data, State, read_link_info);
+handle_op(?SSH_FXP_STAT, ReqId, Data, State) ->
+ stat((State#state.xf)#ssh_xfer.vsn, ReqId, Data, State, read_file_info);
+handle_op(?SSH_FXP_FSTAT, ReqId, Data, State) ->
+ fstat((State#state.xf)#ssh_xfer.vsn, ReqId, Data, State);
+handle_op(?SSH_FXP_OPEN, ReqId, Data, State) ->
+ open((State#state.xf)#ssh_xfer.vsn, ReqId, Data, State);
+handle_op(?SSH_FXP_READ, ReqId, <<?UINT32(HLen), BinHandle:HLen/binary,
+ ?UINT64(Offset), ?UINT32(Len)>>,
+ State) ->
+ case get_handle(State#state.handles, BinHandle) of
+ {_Handle, file, {_Path, IoDevice}} ->
+ read_file(ReqId, IoDevice, Offset, Len, State);
+ _ ->
+ ssh_xfer:xf_send_status(State#state.xf, ReqId,
+ ?SSH_FX_INVALID_HANDLE),
+ State
+ end;
+handle_op(?SSH_FXP_WRITE, ReqId,
+ <<?UINT32(HLen), BinHandle:HLen/binary, ?UINT64(Offset),
+ ?UINT32(Len), Data:Len/binary>>, State) ->
+ case get_handle(State#state.handles, BinHandle) of
+ {_Handle, file, {_Path, IoDevice}} ->
+ write_file(ReqId, IoDevice, Offset, Data, State);
+ _ ->
+ ssh_xfer:xf_send_status(State#state.xf, ReqId,
+ ?SSH_FX_INVALID_HANDLE),
+ State
+ end;
+handle_op(?SSH_FXP_READLINK, ReqId, <<?UINT32(PLen), BPath:PLen/binary>>,
+ State = #state{file_handler = FileMod, file_state = FS0}) ->
+ RelPath = binary_to_list(BPath),
+ AbsPath = relate_file_name(RelPath, State),
+ {Res, FS1} = FileMod:read_link(AbsPath, FS0),
+ case Res of
+ {ok, NewPath} ->
+ ssh_xfer:xf_send_name(State#state.xf, ReqId, NewPath,
+ #ssh_xfer_attr{type=regular});
+ {error, Error} ->
+ ssh_xfer:xf_send_status(State#state.xf, ReqId,
+ ssh_xfer:encode_erlang_status(Error))
+ end,
+ State#state{file_state = FS1};
+handle_op(?SSH_FXP_SETSTAT, ReqId, <<?UINT32(PLen), BPath:PLen/binary,
+ Attr/binary>>, State0) ->
+ Path = relate_file_name(BPath, State0),
+ {Status, State1} = set_stat(Attr, Path, State0),
+ send_status(Status, ReqId, State1);
+handle_op(?SSH_FXP_MKDIR, ReqId, <<?UINT32(PLen), BPath:PLen/binary,
+ Attr/binary>>,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ Path = relate_file_name(BPath, State0),
+ {Res, FS1} = FileMod:make_dir(Path, FS0),
+ State1 = State0#state{file_state = FS1},
+ case Res of
+ ok ->
+ {_, State2} = set_stat(Attr, Path, State1),
+ send_status(ok, ReqId, State2);
+ {error, Error} ->
+ send_status({error, Error}, ReqId, State1)
+ end;
+handle_op(?SSH_FXP_FSETSTAT, ReqId, <<?UINT32(HLen), BinHandle:HLen/binary,
+ Attr/binary>>,
+ State0 = #state{handles = Handles}) ->
+
+ case get_handle(Handles, BinHandle) of
+ {_Handle, _Type, {Path,_}} ->
+ {Status, State1} = set_stat(Attr, Path, State0),
+ send_status(Status, ReqId, State1);
+ _ ->
+ ssh_xfer:xf_send_status(State0#state.xf, ReqId,
+ ?SSH_FX_INVALID_HANDLE),
+ State0
+ end;
+handle_op(?SSH_FXP_REMOVE, ReqId, <<?UINT32(PLen), BPath:PLen/binary>>,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ Path = relate_file_name(BPath, State0),
+ %% case FileMod:is_dir(Path) of %% This version 6 we still have ver 5
+ %% true ->
+ %% ssh_xfer:xf_send_status(State#state.xf, ReqId,
+ %% ?SSH_FX_FILE_IS_A_DIRECTORY);
+ %% false ->
+ {Status, FS1} = FileMod:delete(Path, FS0),
+ State1 = State0#state{file_state = FS1},
+ send_status(Status, ReqId, State1);
+ %%end;
+handle_op(?SSH_FXP_RMDIR, ReqId, <<?UINT32(PLen), BPath:PLen/binary>>,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ Path = relate_file_name(BPath, State0),
+ {Status, FS1} = FileMod:del_dir(Path, FS0),
+ State1 = State0#state{file_state = FS1},
+ send_status(Status, ReqId, State1);
+
+handle_op(?SSH_FXP_RENAME, ReqId,
+ Bin = <<?UINT32(PLen), _:PLen/binary, ?UINT32(PLen2),
+ _:PLen2/binary>>,
+ State = #state{xf = #ssh_xfer{vsn = Vsn}}) when Vsn==3; Vsn==4 ->
+ handle_op(?SSH_FXP_RENAME, ReqId, <<Bin/binary, 0:32>>, State);
+
+handle_op(?SSH_FXP_RENAME, ReqId,
+ <<?UINT32(PLen), BPath:PLen/binary, ?UINT32(PLen2),
+ BPath2:PLen2/binary, ?UINT32(Flags)>>,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ Path = relate_file_name(BPath, State0),
+ Path2 = relate_file_name(BPath2, State0),
+ case Flags band ?SSH_FXP_RENAME_ATOMIC of
+ 0 ->
+ case Flags band ?SSH_FXP_RENAME_OVERWRITE of
+ 0 ->
+ {Res, FS1} = FileMod:read_link_info(Path2, FS0),
+ State1 = State0#state{file_state = FS1},
+ case Res of
+ {ok, _Info} ->
+ ssh_xfer:xf_send_status(
+ State1#state.xf,
+ ReqId,
+ ?SSH_FX_FILE_ALREADY_EXISTS),
+ State1;
+ _ ->
+ rename(Path, Path2, ReqId, State1)
+ end;
+ _ ->
+ rename(Path, Path2, ReqId, State0)
+ end;
+ _ ->
+ ssh_xfer:xf_send_status(State0#state.xf, ReqId,
+ ?SSH_FX_OP_UNSUPPORTED),
+ State0
+ end;
+handle_op(?SSH_FXP_SYMLINK, ReqId,
+ <<?UINT32(PLen), BPath:PLen/binary, ?UINT32(PLen2),
+ BPath2:PLen2/binary>>,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ Path = relate_file_name(BPath, State0),
+ Path2 = relate_file_name(BPath2, State0),
+ {Status, FS1} = FileMod:make_symlink(Path2, Path, FS0),
+ State1 = State0#state{file_state = FS1},
+ send_status(Status, ReqId, State1).
+
+new_handle([], H) ->
+ H;
+new_handle([{N, _} | Rest], H) when N > H ->
+ new_handle(Rest, N+1);
+new_handle([_ | Rest], H) ->
+ new_handle(Rest, H).
+
+add_handle(State, XF, ReqId, Type, DirFileTuple) ->
+ Handles = State#state.handles,
+ Handle = new_handle(Handles, 0),
+ ssh_xfer:xf_send_handle(XF, ReqId, integer_to_list(Handle)),
+ State#state{handles = [{Handle, Type, DirFileTuple} | Handles]}.
+
+get_handle(Handles, BinHandle) ->
+ case (catch list_to_integer(binary_to_list(BinHandle))) of
+ I when is_integer(I) ->
+ case lists:keysearch(I, 1, Handles) of
+ {value, T} -> T;
+ false -> error
+ end;
+ _ ->
+ error
+ end.
+
+%%% read_dir/5: read directory, send names, and return new state
+read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
+ XF, ReqId, Handle, RelPath, {cache, Files}) ->
+ AbsPath = relate_file_name(RelPath, State0),
+ ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
+ if
+ length(Files) > MaxLength ->
+ {ToSend, NewCache} = lists:split(MaxLength, Files),
+ {NamesAndAttrs, FS1} = get_attrs(AbsPath, ToSend, FileMod, FS0),
+ ssh_xfer:xf_send_names(XF, ReqId, NamesAndAttrs),
+ Handles = lists:keyreplace(Handle, 1,
+ State0#state.handles,
+ {Handle, directory, {RelPath,{cache, NewCache}}}),
+ State0#state{handles = Handles, file_state = FS1};
+ true ->
+ {NamesAndAttrs, FS1} = get_attrs(AbsPath, Files, FileMod, FS0),
+ ssh_xfer:xf_send_names(XF, ReqId, NamesAndAttrs),
+ Handles = lists:keyreplace(Handle, 1,
+ State0#state.handles,
+ {Handle, directory, {RelPath,eof}}),
+ State0#state{handles = Handles, file_state = FS1}
+ end;
+read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
+ XF, ReqId, Handle, RelPath, _Status) ->
+ AbsPath = relate_file_name(RelPath, State0),
+ ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
+ {Res, FS1} = FileMod:list_dir(AbsPath, FS0),
+ case Res of
+ {ok, Files} when MaxLength == 0 orelse MaxLength > length(Files) ->
+ {NamesAndAttrs, FS2} = get_attrs(AbsPath, Files, FileMod, FS1),
+ ssh_xfer:xf_send_names(XF, ReqId, NamesAndAttrs),
+ Handles = lists:keyreplace(Handle, 1,
+ State0#state.handles,
+ {Handle, directory, {RelPath,eof}}),
+ State0#state{handles = Handles, file_state = FS2};
+ {ok, Files} ->
+ {ToSend, Cache} = lists:split(MaxLength, Files),
+ {NamesAndAttrs, FS2} = get_attrs(AbsPath, ToSend, FileMod, FS1),
+ ssh_xfer:xf_send_names(XF, ReqId, NamesAndAttrs),
+ Handles = lists:keyreplace(Handle, 1,
+ State0#state.handles,
+ {Handle, directory, {RelPath,{cache, Cache}}}),
+ State0#state{handles = Handles, file_state = FS2};
+ {error, Error} ->
+ State1 = State0#state{file_state = FS1},
+ send_status({error, Error}, ReqId, State1)
+ end.
+
+
+%%% get_attrs: get stat of each file and return
+get_attrs(RelPath, Files, FileMod, FS) ->
+ get_attrs(RelPath, Files, FileMod, FS, []).
+
+get_attrs(_RelPath, [], _FileMod, FS, Acc) ->
+ {lists:reverse(Acc), FS};
+get_attrs(RelPath, [F | Rest], FileMod, FS0, Acc) ->
+ Path = filename:absname(F, RelPath),
+ ?dbg(true, "get_attrs fun: F=~p\n", [F]),
+ case FileMod:read_link_info(Path, FS0) of
+ {{ok, Info}, FS1} ->
+ Attrs = ssh_sftp:info_to_attr(Info),
+ get_attrs(RelPath, Rest, FileMod, FS1, [{F, Attrs} | Acc]);
+ {{error, enoent}, FS1} ->
+ get_attrs(RelPath, Rest, FileMod, FS1, Acc);
+ {Error, FS1} ->
+ {Error, FS1}
+ end.
+
+close_our_file({_,Fd}, FileMod, FS0) ->
+ {_Res, FS1} = FileMod:close(Fd, FS0),
+ FS1.
+
+%%% stat: do the stat
+stat(Vsn, ReqId, Data, State, F) when Vsn =< 3->
+ <<?UINT32(BLen), BPath:BLen/binary>> = Data,
+ stat(ReqId, binary_to_list(BPath), State, F);
+stat(Vsn, ReqId, Data, State, F) when Vsn >= 4->
+ <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(_Flags)>> = Data,
+ stat(ReqId, binary_to_list(BPath), State, F).
+
+fstat(Vsn, ReqId, Data, State) when Vsn =< 3->
+ <<?UINT32(HLen), Handle:HLen/binary>> = Data,
+ fstat(ReqId, Handle, State);
+fstat(Vsn, ReqId, Data, State) when Vsn >= 4->
+ <<?UINT32(HLen), Handle:HLen/binary, ?UINT32(_Flags)>> = Data,
+ fstat(ReqId, Handle, State).
+
+fstat(ReqId, BinHandle, State) ->
+ case get_handle(State#state.handles, BinHandle) of
+ {_Handle, _Type, {Path, _}} ->
+ stat(ReqId, Path, State, read_file_info);
+ _ ->
+ ssh_xfer:xf_send_status(State#state.xf, ReqId,
+ ?SSH_FX_INVALID_HANDLE),
+ State
+ end.
+
+stat(ReqId, RelPath, State0=#state{file_handler=FileMod,
+ file_state=FS0}, F) ->
+ AbsPath = relate_file_name(RelPath, State0),
+ XF = State0#state.xf,
+ ?dbg(false, "stat: AbsPath=~p\n", [AbsPath]),
+ {Res, FS1} = FileMod:F(AbsPath, FS0),
+ State1 = State0#state{file_state = FS1},
+ case Res of
+ {ok, FileInfo} ->
+ ssh_xfer:xf_send_attr(XF, ReqId,
+ ssh_sftp:info_to_attr(FileInfo)),
+ State1;
+ {error, E} ->
+ send_status({error, E}, ReqId, State1)
+ end.
+
+decode_4_open_flag(create_new) ->
+ [write];
+decode_4_open_flag(create_truncate) ->
+ [write];
+decode_4_open_flag(truncate_existing) ->
+ [write];
+decode_4_open_flag(open_existing) ->
+ [read].
+
+decode_4_flags([OpenFlag | Flags]) ->
+ decode_4_flags(Flags, decode_4_open_flag(OpenFlag)).
+
+decode_4_flags([], Flags) ->
+ Flags;
+decode_4_flags([append_data|R], _Flags) ->
+ decode_4_flags(R, [append]);
+decode_4_flags([append_data_atomic|R], _Flags) ->
+ decode_4_flags(R, [append]);
+decode_4_flags([_|R], Flags) ->
+ decode_4_flags(R, Flags).
+
+decode_4_access_flag(read_data) ->
+ [read];
+decode_4_access_flag(list_directory) ->
+ [read];
+decode_4_access_flag(write_data) ->
+ [write];
+decode_4_access_flag(add_file) ->
+ [write];
+decode_4_access_flag(add_subdirectory) ->
+ [read];
+decode_4_access_flag(append_data) ->
+ [append];
+decode_4_access_flag(_) ->
+ [read].
+
+decode_4_acess([_ | _] = Flags) ->
+ lists:map(fun(Flag) ->
+ [decode_4_access_flag(Flag)]
+ end, Flags);
+decode_4_acess([]) ->
+ [].
+
+open(Vsn, ReqId, Data, State) when Vsn =< 3 ->
+ <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(PFlags),
+ _Attrs/binary>> = Data,
+ Path = binary_to_list(BPath),
+ Flags = ssh_xfer:decode_open_flags(Vsn, PFlags) -- [creat, excl, trunc],
+ ?dbg(true, "open: Flags=~p\n", [Flags]),
+ do_open(ReqId, State, Path, Flags);
+open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
+ <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(Access),
+ ?UINT32(PFlags), _Attrs/binary>> = Data,
+ Path = binary_to_list(BPath),
+ FlagBits = ssh_xfer:decode_open_flags(Vsn, PFlags),
+ AcessBits = ssh_xfer:decode_ace_mask(Access),
+ ?dbg(true, "open: Fl=~p\n", [FlagBits]),
+ %% TODO: This is to make sure the Access flags are not ignored
+ %% but this should be thought through better. This solution should
+ %% be considered a hack in order to buy some time. At least
+ %% it works better than when the Access flags where totally ignored.
+ %% A better solution may need some code refactoring that we do
+ %% not have time for right now.
+ AcessFlags = decode_4_acess(AcessBits),
+ Flags = lists:append(lists:umerge(
+ [[decode_4_flags(FlagBits)] | AcessFlags])),
+
+ ?dbg(true, "open: Flags=~p\n", [Flags]),
+
+ do_open(ReqId, State, Path, Flags).
+
+do_open(ReqId, State0, Path, Flags) ->
+ #state{file_handler = FileMod, file_state = FS0, root = Root} = State0,
+ XF = State0#state.xf,
+ F = [raw, binary | Flags],
+ %% case FileMod:is_dir(Path) of %% This is version 6 we still have 5
+ %% true ->
+ %% ssh_xfer:xf_send_status(State#state.xf, ReqId,
+ %% ?SSH_FX_FILE_IS_A_DIRECTORY);
+ %% false ->
+
+ AbsPath = case Root of
+ "" ->
+ Path;
+ _ ->
+ relate_file_name(Path, State0)
+ end,
+
+ {Res, FS1} = FileMod:open(AbsPath, F, FS0),
+ State1 = State0#state{file_state = FS1},
+ case Res of
+ {ok, IoDevice} ->
+ add_handle(State1, XF, ReqId, file, {Path,IoDevice});
+ {error, Error} ->
+ ssh_xfer:xf_send_status(State1#state.xf, ReqId,
+ ssh_xfer:encode_erlang_status(Error)),
+ State1
+ end.
+
+%% resolve all symlinks in a path
+resolve_symlinks(Path, State) ->
+ resolve_symlinks(Path, _LinkCnt=32, State).
+
+resolve_symlinks(Path, LinkCnt, State0) ->
+ resolve_symlinks_2(filename:split(Path), State0, LinkCnt, []).
+
+resolve_symlinks_2(_Path, State, LinkCnt, _AccPath) when LinkCnt =:= 0 ->
+ %% Too many links (there might be a symlink loop)
+ {{error, emlink}, State};
+resolve_symlinks_2(["." | RestPath], State0, LinkCnt, AccPath) ->
+ resolve_symlinks_2(RestPath, State0, LinkCnt, AccPath);
+resolve_symlinks_2([".." | RestPath], State0, LinkCnt, AccPath) ->
+ %% Remove the last path component
+ AccPathComps0 = filename:split(AccPath),
+ Path = case lists:reverse(tl(lists:reverse(AccPathComps0))) of
+ [] ->
+ "";
+ AccPathComps ->
+ filename:join(AccPathComps)
+ end,
+ resolve_symlinks_2(RestPath, State0, LinkCnt, Path);
+resolve_symlinks_2([PathComp | RestPath], State0, LinkCnt, AccPath0) ->
+ #state{file_handler = FileMod, file_state = FS0} = State0,
+ AccPath1 = filename:join(AccPath0, PathComp),
+ {Res, FS1} = FileMod:read_link(AccPath1, FS0),
+ State1 = State0#state{file_state = FS1},
+ case Res of
+ {ok, Target0} -> % path is a symlink
+ %% The target may be a relative or an absolute path and
+ %% may contain symlinks
+ Target1 = filename:absname(Target0, AccPath0),
+ {FollowRes, State2} = resolve_symlinks(Target1, LinkCnt-1, State1),
+ case FollowRes of
+ {ok, Target} ->
+ resolve_symlinks_2(RestPath, State2, LinkCnt-1, Target);
+ {error, _} = Error ->
+ {Error, State2}
+ end;
+ {error, einval} -> % path exists, but is not a symlink
+ resolve_symlinks_2(RestPath, State1, LinkCnt, AccPath1);
+ {error, _} = Error ->
+ {Error, State1}
+ end;
+resolve_symlinks_2([], State, _LinkCnt, AccPath) ->
+ {{ok, AccPath}, State}.
+
+
+relate_file_name(File, State) ->
+ relate_file_name(File, State, _Canonicalize=true).
+
+relate_file_name(File, State, Canonicalize) when is_binary(File) ->
+ relate_file_name(binary_to_list(File), State, Canonicalize);
+relate_file_name(File, #state{cwd = CWD, root = ""}, Canonicalize) ->
+ relate_filename_to_path(File, CWD, Canonicalize);
+relate_file_name(File, #state{root = Root}, Canonicalize) ->
+ case is_within_root(Root, File) of
+ true ->
+ File;
+ false ->
+ RelFile = make_relative_filename(File),
+ NewFile = relate_filename_to_path(RelFile, Root, Canonicalize),
+ case is_within_root(Root, NewFile) of
+ true ->
+ NewFile;
+ false ->
+ Root
+ end
+ end.
+
+is_within_root(Root, File) ->
+ lists:prefix(Root, File).
+
+%% Remove leading slash (/), if any, in order to make the filename
+%% relative (to the root)
+make_relative_filename("/") -> "./"; % Make it relative and preserve /
+make_relative_filename("/"++File) -> File;
+make_relative_filename(File) -> File.
+
+relate_filename_to_path(File0, Path, Canonicalize) ->
+ File1 = filename:absname(File0, Path),
+ File2 = if Canonicalize -> canonicalize_filename(File1);
+ true -> File1
+ end,
+ ensure_trailing_slash_is_preserved(File0, File2).
+
+%% It seems as if the openssh client (observed with the
+%% openssh-4.2p1-18.30 package on SLED 10), and possibly other clients
+%% as well (Maverick?), rely on the fact that a trailing slash (/) is
+%% preserved. If trailing slashes aren't preserved, symlinks which
+%% point at directories won't be properly identified as directories.
+%%
+%% A failing example:
+%%
+%% 1) assume the following directory structure:
+%% $ mkdir /tmp/symlink-target
+%% $ touch /tmp/symlink-target/foo
+%% $ ln -s /tmp/symlink-target /tmp/symlink
+%%
+%% 2) login using the sftp client in openssh
+%% sftp> cd /tmp/
+%% sftp> ls symlink-target
+%% symlink-target/foo
+%% sftp> ls symlink
+%% symlink/ <===== foo should have been visible here
+%% sftp> cd symlink-target
+%% sftp> ls
+%% foo
+%% sftp> cd ..
+%% sftp> cd symlink
+%% sftp> ls
+%% <===== foo should have been visible here
+%%
+%% The symlinks are resolved by file:read_link_info/1 only if the path
+%% has a trailing slash, which seems to something that some of the
+%% sftp clients utilize:
+%%
+%% 1> file:read_link_info(".../symlink").
+%% {ok,{file_info,4,symlink,read_write,
+%% {{2008,10,20},{10,25,26}},
+%% {{2008,10,17},{16,22,33}},
+%% {{2008,10,17},{16,22,33}},
+%% 41471,1,2053,0,570447,20996,9935}}
+%%
+%% 2> file:read_link_info(".../symlink/").
+%% {ok,{file_info,8192,directory,read_write,
+%% {{2008,10,20},{10,36,2}},
+%% {{2008,10,20},{10,44,35}},
+%% {{2008,10,20},{10,44,35}},
+%% 17407,29,2053,0,521224,0,0}}
+ensure_trailing_slash_is_preserved(File0, File1) ->
+ case {lists:suffix("/", File0), lists:suffix("/", File1)} of
+ {true, false} -> File1 ++ "/";
+ _Other -> File1
+ end.
+
+
+
+%%% fix file just a little: a/b/.. -> a and a/. -> a
+canonicalize_filename(File0) ->
+ File = filename:join(canonicalize_filename_2(filename:split(File0), [])),
+ ensure_trailing_slash_is_preserved(File0, File).
+
+canonicalize_filename_2([".." | Rest], ["/"] = Acc) ->
+ canonicalize_filename_2(Rest, Acc);
+canonicalize_filename_2([".." | Rest], [_Dir | Paths]) ->
+ canonicalize_filename_2(Rest, Paths);
+canonicalize_filename_2(["." | Rest], Acc) ->
+ canonicalize_filename_2(Rest, Acc);
+canonicalize_filename_2([A | Rest], Acc) ->
+ canonicalize_filename_2(Rest, [A | Acc]);
+canonicalize_filename_2([], Acc) ->
+ lists:reverse(Acc).
+
+%% return a filename which is relative to the root directory
+%% (any filename that's outside the root directory is forced to the root)
+chroot_filename(Filename, #state{root = Root}) ->
+ FilenameComps0 = filename:split(Filename),
+ RootComps = filename:split(Root),
+ filename:join(chroot_filename_2(FilenameComps0, RootComps)).
+
+chroot_filename_2([PathComp | FilenameRest], [PathComp | RootRest]) ->
+ chroot_filename_2(FilenameRest, RootRest);
+chroot_filename_2(FilenameComps, []) when length(FilenameComps) > 0 ->
+ %% Ensure there's a leading / (filename:join above will take care
+ %% of any duplicates)
+ ["/" | FilenameComps];
+chroot_filename_2(_FilenameComps, _RootComps) ->
+ %% The filename is either outside the root or at the root. In
+ %% both cases we want to force the filename to the root.
+ ["/"].
+
+
+read_file(ReqId, IoDevice, Offset, Len,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ {Res1, FS1} = FileMod:position(IoDevice, {bof, Offset}, FS0),
+ case Res1 of
+ {ok, _NewPos} ->
+ {Res2, FS2} = FileMod:read(IoDevice, Len, FS1),
+ State1 = State0#state{file_state = FS2},
+ case Res2 of
+ {ok, Data} ->
+ ssh_xfer:xf_send_data(State1#state.xf, ReqId, Data),
+ State1;
+ {error, Error} ->
+ send_status({error, Error}, ReqId, State1);
+ eof ->
+ send_status(eof, ReqId, State1)
+ end;
+ {error, Error} ->
+ State1 = State0#state{file_state = FS1},
+ send_status({error, Error}, ReqId, State1)
+ end.
+
+write_file(ReqId, IoDevice, Offset, Data,
+ State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ {Res, FS1} = FileMod:position(IoDevice, {bof, Offset}, FS0),
+ case Res of
+ {ok, _NewPos} ->
+ {Status, FS2} = FileMod:write(IoDevice, Data, FS1),
+ State1 = State0#state{file_state = FS2},
+ send_status(Status, ReqId, State1);
+ {error, Error} ->
+ State1 = State0#state{file_state = FS1},
+ send_status({error, Error}, ReqId, State1)
+ end.
+
+get_status(ok) ->
+ ?SSH_FX_OK;
+get_status(eof) ->
+ ?SSH_FX_EOF;
+get_status({error,Error}) ->
+ ssh_xfer:encode_erlang_status(Error).
+
+send_status(Status, ReqId, State) ->
+ ssh_xfer:xf_send_status(State#state.xf, ReqId, get_status(Status)),
+ State.
+
+set_stat(<<>>, _Path, State) ->
+ {ok, State};
+set_stat(Attr, Path,
+ State0 = #state{file_handler=FileMod, file_state=FS0}) ->
+ {DecodedAttr, _Rest} =
+ ssh_xfer:decode_ATTR((State0#state.xf)#ssh_xfer.vsn, Attr),
+ ?dbg(true, "set_stat DecodedAttr=~p\n", [DecodedAttr]),
+ Info = ssh_sftp:attr_to_info(DecodedAttr),
+ {Res1, FS1} = FileMod:read_link_info(Path, FS0),
+ case Res1 of
+ {ok, OldInfo} ->
+ NewInfo = set_file_info(Info, OldInfo),
+ ?dbg(true, "set_stat Path=~p\nInfo=~p\nOldInfo=~p\nNewInfo=~p\n",
+ [Path, Info, OldInfo, NewInfo]),
+ {Res2, FS2} = FileMod:write_file_info(Path, NewInfo, FS1),
+ State1 = State0#state{file_state = FS2},
+ {Res2, State1};
+ {error, Error} ->
+ State1 = State0#state{file_state = FS1},
+ {{error, Error}, State1}
+ end.
+
+
+set_file_info_sel(undefined, F) ->
+ F;
+set_file_info_sel(F, _) ->
+ F.
+
+set_file_info(#file_info{atime = Dst_atime, mtime = Dst_mtime,
+ ctime = Dst_ctime,
+ mode = Dst_mode, uid = Dst_uid, gid = Dst_gid},
+ #file_info{atime = Src_atime, mtime = Src_mtime,
+ ctime = Src_ctime,
+ mode = Src_mode, uid = Src_uid, gid = Src_gid}) ->
+ #file_info{atime = set_file_info_sel(Dst_atime, Src_atime),
+ mtime = set_file_info_sel(Dst_mtime, Src_mtime),
+ ctime = set_file_info_sel(Dst_ctime, Src_ctime),
+ mode = set_file_info_sel(Dst_mode, Src_mode),
+ uid = set_file_info_sel(Dst_uid, Src_uid),
+ gid = set_file_info_sel(Dst_gid, Src_gid)}.
+
+rename(Path, Path2, ReqId, State0) ->
+ #state{file_handler = FileMod, file_state = FS0} = State0,
+ {Status, FS1} = FileMod:rename(Path, Path2, FS0),
+ State1 = State0#state{file_state = FS1},
+ send_status(Status, ReqId, State1).
diff --git a/lib/ssh/src/ssh_sftpd_file.erl b/lib/ssh/src/ssh_sftpd_file.erl
new file mode 100644
index 0000000000..f0b6bb4de5
--- /dev/null
+++ b/lib/ssh/src/ssh_sftpd_file.erl
@@ -0,0 +1,83 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: Default Callback module for ssh_sftpd
+
+-module(ssh_sftpd_file).
+
+-behaviour(ssh_sftpd_file_api).
+
+%% API
+-export([close/2, delete/2, del_dir/2, get_cwd/1, is_dir/2, list_dir/2,
+ make_dir/2, make_symlink/3, open/3, position/3, read/3,
+ read_file_info/2, read_link/2, read_link_info/2, rename/3,
+ write/3, write_file_info/3]).
+
+close(IoDevice, State) ->
+ {file:close(IoDevice), State}.
+
+delete(Path, State) ->
+ {file:delete(Path), State}.
+
+del_dir(Path, State) ->
+ {file:del_dir(Path), State}.
+
+get_cwd(State) ->
+ {file:get_cwd(), State}.
+
+is_dir(AbsPath, State) ->
+ {filelib:is_dir(AbsPath), State}.
+
+list_dir(AbsPath, State) ->
+ {file:list_dir(AbsPath), State}.
+
+make_dir(Dir, State) ->
+ {file:make_dir(Dir), State}.
+
+make_symlink(Path2, Path, State) ->
+ {file:make_symlink(Path2, Path), State}.
+
+open(Path, Flags, State) ->
+ {file:open(Path, Flags), State}.
+
+position(IoDevice, Offs, State) ->
+ {file:position(IoDevice, Offs), State}.
+
+read(IoDevice, Len, State) ->
+ {file:read(IoDevice, Len), State}.
+
+read_link(Path, State) ->
+ {file:read_link(Path), State}.
+
+read_link_info(Path, State) ->
+ {file:read_link_info(Path), State}.
+
+read_file_info(Path, State) ->
+ {file:read_file_info(Path), State}.
+
+rename(Path, Path2, State) ->
+ {file:rename(Path, Path2), State}.
+
+write(IoDevice, Data, State) ->
+ {file:write(IoDevice, Data), State}.
+
+write_file_info(Path,Info, State) ->
+ {file:write_file_info(Path, Info), State}.
diff --git a/lib/ssh/src/ssh_sftpd_file_api.erl b/lib/ssh/src/ssh_sftpd_file_api.erl
new file mode 100644
index 0000000000..8decfb38d9
--- /dev/null
+++ b/lib/ssh/src/ssh_sftpd_file_api.erl
@@ -0,0 +1,47 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_sftpd_file_api).
+
+-export([behaviour_info/1]).
+
+behaviour_info(callbacks) ->
+ [
+ {close, 2},
+ {delete, 2},
+ {del_dir, 2},
+ {get_cwd, 1},
+ {is_dir, 2},
+ {list_dir, 2},
+ {make_dir, 2},
+ {make_symlink, 3},
+ {open, 3},
+ {position, 3},
+ {read, 3},
+ {read_file_info, 2},
+ {read_link, 2},
+ {read_link_info, 2},
+ {rename, 3},
+ {write, 3},
+ {write_file_info, 3}
+ ];
+behaviour_info(_) ->
+ undefined.
diff --git a/lib/ssh/src/ssh_shell.erl b/lib/ssh/src/ssh_shell.erl
new file mode 100644
index 0000000000..f81b949119
--- /dev/null
+++ b/lib/ssh/src/ssh_shell.erl
@@ -0,0 +1,178 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_shell).
+
+-include("ssh_connect.hrl").
+
+-behaviour(ssh_channel).
+
+%% ssh_channel callbacks
+-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
+
+%% Spawn export
+-export([input_loop/2]).
+
+-record(state,
+ {
+ io, %% Io process
+ channel, %% Id of the ssh channel
+ cm %% Ssh connection manager
+ }
+ ).
+
+%%====================================================================
+%% ssh_channel callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State}
+%%
+%% Description: Initiates the CLI
+%%--------------------------------------------------------------------
+init([ConnectionManager, ChannelId] = Args) ->
+
+ %% Make sure that we are proclib compatible as
+ %% this client should be runnable from the
+ %% erlang shell.
+ case get('$initial_call') of
+ undefined ->
+ Me = get_my_name(),
+ Ancestors = get_ancestors(),
+ put('$ancestors', [Me | Ancestors]),
+ put('$initial_call', {?MODULE, init, Args});
+ _ ->
+ ok
+ end,
+
+ case ssh_connection:shell(ConnectionManager, ChannelId) of
+ ok ->
+ {group_leader, GIO} =
+ process_info(self(), group_leader),
+ IoPid = spawn_link(?MODULE, input_loop,
+ [GIO, self()]),
+ {ok, #state{io = IoPid,
+ channel = ChannelId,
+ cm = ConnectionManager}};
+ Error ->
+ {stop, Error}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles channel messages received on the ssh-connection.
+%%--------------------------------------------------------------------
+handle_ssh_msg({ssh_cm, _, {data, _ChannelId, 0, Data}}, State) ->
+ %% TODO: When unicode support is ready
+ %% should we call this function or perhaps a new
+ %% function.
+ io:put_chars(Data),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _,
+ {data, _ChannelId, ?SSH_EXTENDED_DATA_STDERR, Data}},
+ State) ->
+ %% TODO: When unicode support is ready
+ %% should we call this function or perhaps a new
+ %% function.
+ io:put_chars(Data),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {eof, _ChannelId}}, State) ->
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
+ %% Ignore signals according to RFC 4254 section 6.9.
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}}, State) ->
+ io:put_chars("Connection closed by peer"),
+ %% TODO: When unicode support is ready
+ %% should we call this function or perhaps a new
+ %% function. The error is encoded as UTF-8!
+ io:put_chars(Error),
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, 0}}, State) ->
+ io:put_chars("logout"),
+ io:put_chars("Connection closed"),
+ {stop, ChannelId, State};
+
+handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State) ->
+ io:put_chars("Connection closed by peer"),
+ io:put_chars("Status: " ++ integer_to_list(Status)),
+ {stop, ChannelId, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_ssh_msg(Args) -> {ok, State} | {stop, ChannelId, State}
+%%
+%% Description: Handles other channel messages
+%%--------------------------------------------------------------------
+handle_msg({ssh_channel_up, ChannelId, ConnectionManager},
+ #state{channel = ChannelId,
+ cm = ConnectionManager} = State) ->
+ {ok, State};
+
+handle_msg({input, IoPid, eof}, #state{io = IoPid, channel = ChannelId,
+ cm = ConnectionManager} = State) ->
+ ssh_connection:send_eof(ConnectionManager, ChannelId),
+ {ok, State};
+
+handle_msg({input, IoPid, Line}, #state{io = IoPid,
+ channel = ChannelId,
+ cm = ConnectionManager} = State) ->
+ ssh_connection:send(ConnectionManager, ChannelId, Line),
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reasons, State) -> _
+%%
+%% Description: Cleanup when shell channel is terminated
+%%--------------------------------------------------------------------
+terminate(_Reason, #state{io = IoPid}) ->
+ exit(IoPid, kill).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+input_loop(Fd, Pid) ->
+ case io:get_line(Fd, '>') of
+ eof ->
+ Pid ! {input, self(), eof},
+ ok;
+ Line ->
+ Pid ! {input, self(), Line},
+ input_loop (Fd, Pid)
+ end.
+
+get_my_name() ->
+ case process_info(self(),registered_name) of
+ {registered_name,Name} -> Name;
+ _ -> self()
+ end.
+
+get_ancestors() ->
+ case get('$ancestors') of
+ A when is_list(A) -> A;
+ _ -> []
+ end.
diff --git a/lib/ssh/src/ssh_ssh.erl b/lib/ssh/src/ssh_ssh.erl
new file mode 100644
index 0000000000..6be8bf7a5a
--- /dev/null
+++ b/lib/ssh/src/ssh_ssh.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: THIS MODULE IS DEPRECATD AND SHOULD BE REMOVED IN R14
+
+-module(ssh_ssh).
+
+-export([connect/1, connect/2, connect/3]).
+-deprecated({connect, 1, next_major_release}).
+-deprecated({connect, 2, next_major_release}).
+-deprecated({connect, 3, next_major_release}).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+
+-define(default_timeout, 10000).
+
+%%% Backwards compatibility
+connect(A) ->
+ connect(A, []).
+
+connect(Host, Opts) when is_list(Host) ->
+ connect(Host, 22, Opts);
+connect(CM, Opts) ->
+ Timeout = proplists:get_value(connect_timeout, Opts, ?default_timeout),
+ session(CM, Timeout).
+
+connect(Host, Port, Opts) ->
+ case ssh:connect(Host, Port, Opts) of
+ {ok, CM} ->
+ session(CM, proplists:get_value(connect_timeout,
+ Opts, ?default_timeout));
+ Error ->
+ Error
+ end.
+
+session(CM, Timeout) ->
+ case ssh_connection:session_channel(CM, Timeout) of
+ {ok, ChannelId} ->
+ Args = [{channel_cb, ssh_shell},
+ {init_args,[CM, ChannelId]},
+ {cm, CM}, {channel_id, ChannelId}],
+ {ok, State} = ssh_channel:init([Args]),
+ ssh_channel:enter_loop(State);
+ Error ->
+ Error
+ end.
diff --git a/lib/ssh/src/ssh_sshd.erl b/lib/ssh/src/ssh_sshd.erl
new file mode 100644
index 0000000000..4bc0469061
--- /dev/null
+++ b/lib/ssh/src/ssh_sshd.erl
@@ -0,0 +1,48 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Description: This module uses the erlang shell and
+%% ssh_cli to make an erlang sshd
+
+-module(ssh_sshd).
+
+%% API
+-export([listen/0, listen/1, listen/2, listen/3, stop/1]).
+
+-deprecated({listen, 0, next_major_release}).
+-deprecated({listen, 1, next_major_release}).
+-deprecated({listen, 2, next_major_release}).
+-deprecated({listen, 3, next_major_release}).
+-deprecated({stop, 1, next_major_release}).
+
+listen() ->
+ listen(22).
+
+listen(Port) ->
+ listen(Port, []).
+
+listen(Port, Opts) ->
+ listen(any, Port, Opts).
+
+listen(Addr, Port, Opts) ->
+ ssh:daemon(Addr, Port, Opts).
+
+stop(Pid) ->
+ ssh:stop_daemon(Pid).
diff --git a/lib/ssh/src/ssh_subsystem_sup.erl b/lib/ssh/src/ssh_subsystem_sup.erl
new file mode 100644
index 0000000000..17d47a91d5
--- /dev/null
+++ b/lib/ssh/src/ssh_subsystem_sup.erl
@@ -0,0 +1,109 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The ssh subsystem supervisor
+%%----------------------------------------------------------------------
+
+-module(ssh_subsystem_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, connection_supervisor/1, channel_supervisor/1
+ ]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(Opts) ->
+ supervisor:start_link(?MODULE, [Opts]).
+
+connection_supervisor(SupPid) ->
+ Children = supervisor:which_children(SupPid),
+ ssh_connection_sup(Children).
+
+channel_supervisor(SupPid) ->
+ Children = supervisor:which_children(SupPid),
+ ssh_channel_sup(Children).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([Opts]) ->
+ RestartStrategy = one_for_all,
+ MaxR = 0,
+ MaxT = 3600,
+ Children = child_specs(Opts),
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+child_specs(Opts) ->
+ case proplists:get_value(role, Opts) of
+ client ->
+ [ssh_connectinon_child_spec(Opts)];
+ server ->
+ [ssh_connectinon_child_spec(Opts), ssh_channel_child_spec(Opts)]
+ end.
+
+ssh_connectinon_child_spec(Opts) ->
+ Address = proplists:get_value(address, Opts),
+ Port = proplists:get_value(port, Opts),
+ Role = proplists:get_value(role, Opts),
+ Name = id(Role, ssh_connection_controler, Address, Port),
+ StartFunc = {ssh_connection_controler, start_link, [Opts]},
+ Restart = transient,
+% Restart = permanent,
+ Shutdown = 5000,
+ Modules = [ssh_connection_controler],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+ssh_channel_child_spec(Opts) ->
+ Address = proplists:get_value(address, Opts),
+ Port = proplists:get_value(port, Opts),
+ Role = proplists:get_value(role, Opts),
+ Name = id(Role, ssh_channel_sup, Address, Port),
+ StartFunc = {ssh_channel_sup, start_link, [Opts]},
+ Restart = transient,
+% Restart = permanent,
+ Shutdown = infinity,
+ Modules = [ssh_channel_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+id(Role, Sup, Address, Port) ->
+ {Role, Sup, Address, Port}.
+
+ssh_connection_sup([{_, Child, _, [ssh_connection_controler]} | _]) ->
+ Child;
+ssh_connection_sup([_ | Rest]) ->
+ ssh_connection_sup(Rest).
+
+ssh_channel_sup([{_, Child, _, [ssh_channel_sup]} | _]) ->
+ Child;
+ssh_channel_sup([_ | Rest]) ->
+ ssh_channel_sup(Rest).
+
+
+
diff --git a/lib/ssh/src/ssh_sup.erl b/lib/ssh/src/ssh_sup.erl
new file mode 100644
index 0000000000..4c46b1586b
--- /dev/null
+++ b/lib/ssh/src/ssh_sup.erl
@@ -0,0 +1,101 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The top supervisor for the ssh application.
+%%----------------------------------------------------------------------
+-module(ssh_sup).
+
+-behaviour(supervisor).
+
+-export([init/1]).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([]) ->
+ SupFlags = {one_for_one, 10, 3600},
+ Children = children(),
+ {ok, {SupFlags, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+get_services() ->
+ case (catch application:get_env(ssh, services)) of
+ {ok, Services} ->
+ Services;
+ _ ->
+ []
+ end.
+
+children() ->
+ Services = get_services(),
+ Clients = [Service || Service <- Services, is_client(Service)],
+ Servers = [Service || Service <- Services, is_server(Service)],
+
+ [server_child_spec(Servers), client_child_spec(Clients),
+ ssh_userauth_reg_spec()].
+
+server_child_spec(Servers) ->
+ Name = sshd_sup,
+ StartFunc = {sshd_sup, start_link, [Servers]},
+ Restart = permanent,
+ Shutdown = infinity,
+ Modules = [sshd_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+client_child_spec(Clients) ->
+ Name = sshc_sup,
+ StartFunc = {sshc_sup, start_link, [Clients]},
+ Restart = permanent,
+ Shutdown = infinity,
+ Modules = [sshc_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+ssh_userauth_reg_spec() ->
+ Name = ssh_userreg,
+ StartFunc = {ssh_userreg, start_link, []},
+ Restart = transient,
+ Shutdown = 5000,
+ Modules = [ssh_userreg],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+
+is_server({sftpd, _}) ->
+ true;
+is_server({shelld, _}) ->
+ true;
+is_server(_) ->
+ false.
+
+is_client({sftpc, _}) ->
+ true;
+is_client({shellc, _}) ->
+ true;
+is_client(_) ->
+ false.
+
+
+
+
diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl
new file mode 100644
index 0000000000..477f60f993
--- /dev/null
+++ b/lib/ssh/src/ssh_system_sup.erl
@@ -0,0 +1,160 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The ssh server instance supervisor, an instans of this supervisor
+%% exists for every ip-address and port combination, hangs under
+%% sshd_sup.
+%%----------------------------------------------------------------------
+
+-module(ssh_system_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, stop_listener/1,
+ stop_listener/2, stop_system/1,
+ stop_system/2, system_supervisor/2,
+ subsystem_supervisor/1, channel_supervisor/1,
+ connection_supervisor/1,
+ acceptor_supervisor/1, start_subsystem/2, restart_subsystem/2, restart_acceptor/2]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(ServerOpts) ->
+ Address = proplists:get_value(address, ServerOpts),
+ Port = proplists:get_value(port, ServerOpts),
+ Name = make_name(Address, Port),
+ supervisor:start_link({local, Name}, ?MODULE, [ServerOpts]).
+
+stop_listener(SysSup) ->
+ stop_acceptor(SysSup).
+
+stop_listener(Address, Port) ->
+ Name = make_name(Address, Port),
+ stop_acceptor(whereis(Name)).
+
+stop_system(SysSup) ->
+ Name = sshd_sup:system_name(SysSup),
+ sshd_sup:stop_child(Name).
+
+stop_system(Address, Port) ->
+ sshd_sup:stop_child(Address, Port).
+
+system_supervisor(Address, Port) ->
+ Name = make_name(Address, Port),
+ whereis(Name).
+
+subsystem_supervisor(SystemSup) ->
+ ssh_subsystem_sup(supervisor:which_children(SystemSup)).
+
+channel_supervisor(SystemSup) ->
+ SubSysSup = ssh_subsystem_sup(supervisor:which_children(SystemSup)),
+ ssh_subsystem_sup:channel_supervisor(SubSysSup).
+
+connection_supervisor(SystemSup) ->
+ SubSysSup = ssh_subsystem_sup(supervisor:which_children(SystemSup)),
+ ssh_subsystem_sup:connection_supervisor(SubSysSup).
+
+acceptor_supervisor(SystemSup) ->
+ ssh_acceptor_sup(supervisor:which_children(SystemSup)).
+
+start_subsystem(SystemSup, Options) ->
+ Spec = ssh_subsystem_child_spec(Options),
+ supervisor:start_child(SystemSup, Spec).
+
+restart_subsystem(Address, Port) ->
+ SysSupName = make_name(Address, Port),
+ SubSysName = id(ssh_subsystem_sup, Address, Port),
+ case supervisor:terminate_child(SysSupName, SubSysName) of
+ ok ->
+ supervisor:restart_child(SysSupName, SubSysName);
+ Error ->
+ Error
+ end.
+
+restart_acceptor(Address, Port) ->
+ SysSupName = make_name(Address, Port),
+ AcceptorName = id(ssh_acceptor_sup, Address, Port),
+ supervisor:restart_child(SysSupName, AcceptorName).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([ServerOpts]) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = child_specs(ServerOpts),
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+child_specs(ServerOpts) ->
+ [ssh_acceptor_child_spec(ServerOpts)].
+
+ssh_acceptor_child_spec(ServerOpts) ->
+ Address = proplists:get_value(address, ServerOpts),
+ Port = proplists:get_value(port, ServerOpts),
+ Name = id(ssh_acceptor_sup, Address, Port),
+ StartFunc = {ssh_acceptor_sup, start_link, [ServerOpts]},
+ Restart = permanent,
+ Shutdown = infinity,
+ Modules = [ssh_acceptor_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+ssh_subsystem_child_spec(ServerOpts) ->
+ Name = make_ref(),
+ StartFunc = {ssh_subsystem_sup, start_link, [ServerOpts]},
+ Restart = temporary,
+ Shutdown = infinity,
+ Modules = [ssh_subsystem_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+
+id(Sup, Address, Port) ->
+ {Sup, Address, Port}.
+
+make_name(Address, Port) ->
+ list_to_atom(lists:flatten(io_lib:format("ssh_system_~p_~p_sup",
+ [Address, Port]))).
+
+ssh_subsystem_sup([{_, Child, _, [ssh_subsystem_sup]} | _]) ->
+ Child;
+ssh_subsystem_sup([_ | Rest]) ->
+ ssh_subsystem_sup(Rest).
+
+ssh_acceptor_sup([{_, Child, _, [ssh_acceptor_sup]} | _]) ->
+ Child;
+ssh_acceptor_sup([_ | Rest]) ->
+ ssh_acceptor_sup(Rest).
+
+stop_acceptor(Sup) ->
+ [Name] =
+ [SupName || {SupName, _, _, [ssh_acceptor_sup]} <-
+ supervisor:which_children(Sup)],
+ supervisor:terminate_child(Sup, Name).
+
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
new file mode 100644
index 0000000000..5617231c60
--- /dev/null
+++ b/lib/ssh/src/ssh_transport.erl
@@ -0,0 +1,1161 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: SSH transport protocol
+
+-module(ssh_transport).
+
+-include("ssh_transport.hrl").
+
+-include("ssh.hrl").
+-include_lib("kernel/include/inet.hrl").
+
+-export([connect/5, accept/4]).
+-export([versions/2, hello_version_msg/1]).
+-export([next_seqnum/1, decrypt_first_block/2, decrypt_blocks/3,
+ is_valid_mac/3, transport_messages/1, kexdh_messages/0,
+ kex_dh_gex_messages/0, handle_hello_version/1,
+ key_exchange_init_msg/1, key_init/3, new_keys_message/1,
+ handle_kexinit_msg/3, handle_kexdh_init/2,
+ handle_kex_dh_gex_group/2, handle_kex_dh_gex_reply/2,
+ handle_new_keys/2, handle_kex_dh_gex_request/2,
+ handle_kexdh_reply/2,
+ unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1]).
+
+%% debug flagso
+-define(DBG_ALG, true).
+-define(DBG_KEX, true).
+-define(DBG_CRYPTO, false).
+-define(DBG_PACKET, false).
+-define(DBG_MESSAGE, true).
+-define(DBG_BIN_MESSAGE, true).
+-define(DBG_MAC, false).
+-define(DBG_ZLIB, true).
+
+versions(client, Options)->
+ Vsn = proplists:get_value(vsn, Options, ?DEFAULT_CLIENT_VERSION),
+ Version = format_version(Vsn),
+ {Vsn, Version};
+versions(server, Options) ->
+ Vsn = proplists:get_value(vsn, Options, ?DEFAULT_SERVER_VERSION),
+ Version = format_version(Vsn),
+ {Vsn, Version}.
+
+hello_version_msg(Data) ->
+ [Data,"\r\n"].
+
+next_seqnum(SeqNum) ->
+ (SeqNum + 1) band 16#ffffffff.
+
+decrypt_first_block(Bin, #ssh{decrypt_block_size = BlockSize} = Ssh0) ->
+ <<EncBlock:BlockSize/binary, EncData/binary>> = Bin,
+ {Ssh, <<?UINT32(PacketLen), _/binary>> = DecData} =
+ decrypt(Ssh0, EncBlock),
+ {Ssh, PacketLen, DecData, EncData}.
+
+decrypt_blocks(Bin, Length, Ssh0) ->
+ <<EncBlocks:Length/binary, EncData/binary>> = Bin,
+ {Ssh, DecData} = decrypt(Ssh0, EncBlocks),
+ {Ssh, DecData, EncData}.
+
+is_valid_mac(_, _ , #ssh{recv_mac_size = 0}) ->
+ true;
+is_valid_mac(Mac, Data, #ssh{recv_mac = Algorithm,
+ recv_mac_key = Key, recv_sequence = SeqNum}) ->
+ Mac == mac(Algorithm, Key, SeqNum, Data).
+
+transport_messages(_) ->
+ [{ssh_msg_disconnect, ?SSH_MSG_DISCONNECT,
+ [uint32, string, string]},
+
+ {ssh_msg_ignore, ?SSH_MSG_IGNORE,
+ [string]},
+
+ {ssh_msg_unimplemented, ?SSH_MSG_UNIMPLEMENTED,
+ [uint32]},
+
+ {ssh_msg_debug, ?SSH_MSG_DEBUG,
+ [boolean, string, string]},
+
+ {ssh_msg_service_request, ?SSH_MSG_SERVICE_REQUEST,
+ [string]},
+
+ {ssh_msg_service_accept, ?SSH_MSG_SERVICE_ACCEPT,
+ [string]},
+
+ {ssh_msg_kexinit, ?SSH_MSG_KEXINIT,
+ [cookie,
+ name_list, name_list,
+ name_list, name_list,
+ name_list, name_list,
+ name_list, name_list,
+ name_list, name_list,
+ boolean,
+ uint32]},
+
+ {ssh_msg_newkeys, ?SSH_MSG_NEWKEYS,
+ []}
+ ].
+
+kexdh_messages() ->
+ [{ssh_msg_kexdh_init, ?SSH_MSG_KEXDH_INIT,
+ [mpint]},
+
+ {ssh_msg_kexdh_reply, ?SSH_MSG_KEXDH_REPLY,
+ [binary, mpint, binary]}
+ ].
+
+kex_dh_gex_messages() ->
+ [{ssh_msg_kex_dh_gex_request, ?SSH_MSG_KEX_DH_GEX_REQUEST,
+ [uint32, uint32, uint32]},
+
+ {ssh_msg_kex_dh_gex_request_old, ?SSH_MSG_KEX_DH_GEX_REQUEST_OLD,
+ [uint32]},
+
+ {ssh_msg_kex_dh_gex_group, ?SSH_MSG_KEX_DH_GEX_GROUP,
+ [mpint, mpint]},
+
+ {ssh_msg_kex_dh_gex_init, ?SSH_MSG_KEX_DH_GEX_INIT,
+ [mpint]},
+
+ {ssh_msg_kex_dh_gex_reply, ?SSH_MSG_KEX_DH_GEX_REPLY,
+ [binary, mpint, binary]}
+ ].
+
+yes_no(Ssh, Prompt) ->
+ (Ssh#ssh.io_cb):yes_no(Prompt).
+
+connect(ConnectionSup, Address, Port, SocketOpts, Opts) ->
+ Timeout = proplists:get_value(connect_timeout, Opts, infinity),
+ {_, Callback, _} =
+ proplists:get_value(transport, Opts, {tcp, gen_tcp, tcp_closed}),
+ case do_connect(Callback, Address, Port, SocketOpts, Timeout) of
+ {ok, Socket} ->
+ {ok, Pid} =
+ ssh_connection_controler:start_handler_child(ConnectionSup,
+ [client, Socket,
+ [{address, Address},
+ {port, Port} |
+ Opts]]),
+ Callback:controlling_process(Socket, Pid),
+ ssh_connection_handler:send_event(Pid, socket_control),
+ {ok, Pid};
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+do_connect(Callback, Address, Port, SocketOpts, Timeout) ->
+ Opts = [{active, false} | SocketOpts],
+ case Callback:connect(Address, Port, Opts, Timeout) of
+ {error, nxdomain} ->
+ Callback:connect(Address, Port, lists:delete(inet6, Opts), Timeout);
+ {error, eafnosupport} ->
+ Callback:connect(Address, Port, lists:delete(inet6, Opts), Timeout);
+ Other ->
+ Other
+ end.
+
+accept(Address, Port, Socket, Options) ->
+ {_, Callback, _} =
+ proplists:get_value(transport, Options, {tcp, gen_tcp, tcp_closed}),
+ ConnectionSup =
+ ssh_system_sup:connection_supervisor(
+ ssh_system_sup:system_supervisor(Address, Port)),
+ {ok, Pid} =
+ ssh_connection_controler:start_handler_child(ConnectionSup,
+ [server, Socket,
+ [{address, Address},
+ {port, Port} | Options]]),
+ Callback:controlling_process(Socket, Pid),
+ ssh_connection_handler:send_event(Pid, socket_control),
+ {ok, Pid}.
+
+format_version({Major,Minor}) ->
+ "SSH-" ++ integer_to_list(Major) ++ "." ++
+ integer_to_list(Minor) ++ "-Erlang".
+
+handle_hello_version(Version) ->
+ StrVersion = trim_tail(Version),
+ case string:tokens(Version, "-") of
+ [_, "2.0" | _] ->
+ {{2,0}, StrVersion};
+ [_, "1.99" | _] ->
+ {{2,0}, StrVersion};
+ [_, "1.3" | _] ->
+ {{1,3}, StrVersion};
+ [_, "1.5" | _] ->
+ {{1,5}, StrVersion}
+ end.
+
+key_exchange_init_msg(Ssh0) ->
+ Msg = kex_init(Ssh0),
+ {SshPacket, Ssh} = ssh_packet(Msg, Ssh0),
+ {Msg, SshPacket, Ssh}.
+
+kex_init(#ssh{role = Role, opts = Opts}) ->
+ Random = ssh_bits:random(16),
+ Compression = case proplists:get_value(compression, Opts, none) of
+ zlib -> ["zlib", "none"];
+ none -> ["none", "zlib"]
+ end,
+ kexinit_messsage(Role, Random, Compression).
+
+key_init(client, Ssh, Value) ->
+ Ssh#ssh{c_keyinit = Value};
+key_init(server, Ssh, Value) ->
+ Ssh#ssh{s_keyinit = Value}.
+
+kexinit_messsage(client, Random, Compression) ->
+ #ssh_msg_kexinit{
+ cookie = Random,
+ kex_algorithms = ["diffie-hellman-group1-sha1"],
+ server_host_key_algorithms = ["ssh-rsa", "ssh-dss"],
+ encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
+ encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
+ mac_algorithms_client_to_server = ["hmac-sha1"],
+ mac_algorithms_server_to_client = ["hmac-sha1"],
+ compression_algorithms_client_to_server = Compression,
+ compression_algorithms_server_to_client = Compression,
+ languages_client_to_server = [],
+ languages_server_to_client = []
+ };
+
+kexinit_messsage(server, Random, Compression) ->
+ #ssh_msg_kexinit{
+ cookie = Random,
+ kex_algorithms = ["diffie-hellman-group1-sha1"],
+ server_host_key_algorithms = ["ssh-dss"],
+ encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
+ encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
+ mac_algorithms_client_to_server = ["hmac-sha1"],
+ mac_algorithms_server_to_client = ["hmac-sha1"],
+ compression_algorithms_client_to_server = Compression,
+ compression_algorithms_server_to_client = Compression,
+ languages_client_to_server = [],
+ languages_server_to_client = []
+ }.
+
+new_keys_message(Ssh0) ->
+ {SshPacket, Ssh} =
+ ssh_packet(#ssh_msg_newkeys{}, Ssh0),
+ {ok, SshPacket, Ssh}.
+
+handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
+ #ssh{role = client} = Ssh0) ->
+ {ok, Algoritms} = select_algorithm(client, Own, CounterPart),
+ case verify_algorithm(Algoritms) of
+ true ->
+ install_messages(Algoritms#alg.kex),
+ key_exchange_first_msg(Algoritms#alg.kex,
+ Ssh0#ssh{algorithms = Algoritms});
+ _ ->
+ %% TODO: Correct code?
+ throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Selection of key exchange"
+ " algorithm failed",
+ language = "en"})
+ end;
+
+handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
+ #ssh{role = server} = Ssh) ->
+ {ok, Algoritms} = select_algorithm(server, CounterPart, Own),
+ install_messages(Algoritms#alg.kex),
+ {ok, Ssh#ssh{algorithms = Algoritms}}.
+
+
+%% TODO: diffie-hellman-group14-sha1 should also be supported.
+%% Maybe check more things ...
+verify_algorithm(#alg{kex = 'diffie-hellman-group1-sha1'}) ->
+ true;
+verify_algorithm(#alg{kex = 'diffie-hellman-group-exchange-sha1'}) ->
+ true;
+verify_algorithm(_) ->
+ false.
+
+install_messages('diffie-hellman-group1-sha1') ->
+ ssh_bits:install_messages(kexdh_messages());
+install_messages('diffie-hellman-group-exchange-sha1') ->
+ ssh_bits:install_messages(kex_dh_gex_messages()).
+
+key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) ->
+ {G, P} = dh_group1(),
+ {Private, Public} = dh_gen_key(G, P, 1024),
+ %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
+ {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0),
+ {ok, SshPacket,
+ Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}};
+
+key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) ->
+ Min = ?DEFAULT_DH_GROUP_MIN,
+ NBits = ?DEFAULT_DH_GROUP_NBITS,
+ Max = ?DEFAULT_DH_GROUP_MAX,
+ {SshPacket, Ssh1} =
+ ssh_packet(#ssh_msg_kex_dh_gex_request{min = Min,
+ n = NBits, max = Max},
+ Ssh0),
+ {ok, SshPacket,
+ Ssh1#ssh{keyex_info = {Min, Max, NBits}}}.
+
+
+handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
+ {G, P} = dh_group1(),
+ {Private, Public} = dh_gen_key(G, P, 1024),
+ %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
+ K = ssh_math:ipow(E, Private, P),
+ {Key, K_S} = get_host_key(Ssh0),
+ H = kex_h(Ssh0, K_S, E, Public, K),
+ H_SIG = sign_host_key(Ssh0, Key, H),
+ {SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_reply{public_host_key = K_S,
+ f = Public,
+ h_sig = H_SIG
+ }, Ssh0),
+ %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
+ %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+ {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
+ shared_secret = K,
+ exchanged_hash = H,
+ session_id = sid(Ssh1, H)}}.
+
+handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) ->
+ {Private, Public} = dh_gen_key(G,P,1024),
+ %%?dbg(?DBG_KEX, "public: ~p ~n", [Public]),
+ {SshPacket, Ssh1} =
+ ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0),
+ {ok, SshPacket,
+ Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}}.
+
+handle_new_keys(#ssh_msg_newkeys{}, Ssh0) ->
+ try install_alg(Ssh0) of
+ #ssh{} = Ssh ->
+ {ok, Ssh}
+ catch
+ error:_Error -> %% TODO: Throw earlier ....
+ throw(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
+ description = "Install alg failed",
+ language = "en"})
+ end.
+
+
+%% %% Select algorithms
+handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F,
+ h_sig = H_SIG},
+ #ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) ->
+ K = ssh_math:ipow(F, Private, P),
+ H = kex_h(Ssh0, HostKey, Public, F, K),
+ %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
+ %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+ case verify_host_key(Ssh0, HostKey, H, H_SIG) of
+ ok ->
+ {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
+ {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ exchanged_hash = H,
+ session_id = sid(Ssh, H)}};
+ _Error ->
+ Disconnect = #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed",
+ language = "en"},
+ throw(Disconnect)
+ end.
+
+handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = _Min,
+ n = _NBits,
+ max = _Max}, Ssh0) ->
+ {G,P} = dh_group1(), %% TODO real imp this seems to be a hack?!
+ {Private, Public} = dh_gen_key(G, P, 1024),
+ {SshPacket, Ssh} =
+ ssh_packet(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0),
+ {ok, SshPacket,
+ Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}}}.
+
+handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey,
+ f = F,
+ h_sig = H_SIG},
+ #ssh{keyex_key = {{Private, Public}, {G, P}},
+ keyex_info = {Min, Max, NBits}} =
+ Ssh0) ->
+ K = ssh_math:ipow(F, Private, P),
+ H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K),
+ %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
+ %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+ case verify_host_key(Ssh0, HostKey, H, H_SIG) of
+ ok ->
+ {SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
+ {ok, SshPacket, Ssh#ssh{shared_secret = K,
+ exchanged_hash = H,
+ session_id = sid(Ssh, H)}};
+ _Error ->
+ Disconnect = #ssh_msg_disconnect{
+ code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ description = "Key exchange failed",
+ language = "en"},
+ throw(Disconnect)
+ end.
+
+%% select session id
+sid(#ssh{session_id = undefined}, H) ->
+ H;
+sid(#ssh{session_id = Id}, _) ->
+ Id.
+
+%%
+%% The host key should be read from storage
+%%
+get_host_key(SSH) ->
+ #ssh{key_cb = Mod, opts = Opts, algorithms = ALG} = SSH,
+ Scope = proplists:get_value(key_scope, Opts, system),
+ case ALG#alg.hkey of
+ 'ssh-rsa' ->
+ case Mod:private_host_rsa_key(Scope, Opts) of
+ {ok,Key=#ssh_key { public={N,E}} } ->
+ %%?dbg(true, "x~n", []),
+ {Key,
+ ssh_bits:encode(["ssh-rsa",E,N],[string,mpint,mpint])};
+ Error ->
+ %%?dbg(true, "y~n", []),
+ exit(Error)
+ end;
+ 'ssh-dss' ->
+ case Mod:private_host_dsa_key(Scope, Opts) of
+ {ok,Key=#ssh_key { public={P,Q,G,Y}}} ->
+ {Key, ssh_bits:encode(["ssh-dss",P,Q,G,Y],
+ [string,mpint,mpint,mpint,mpint])};
+ Error ->
+ exit(Error)
+ end;
+ _ ->
+ exit({error, bad_key_type})
+ end.
+
+sign_host_key(Ssh, Private, H) ->
+ ALG = Ssh#ssh.algorithms,
+ Module = case ALG#alg.hkey of
+ 'ssh-rsa' ->
+ ssh_rsa;
+ 'ssh-dss' ->
+ ssh_dsa
+ end,
+ case catch Module:sign(Private, H) of
+ {'EXIT', Reason} ->
+ error_logger:format("SIGN FAILED: ~p\n", [Reason]),
+ {error, Reason};
+ SIG ->
+ ssh_bits:encode([Module:alg_name() ,SIG],[string,binary])
+ end.
+
+verify_host_key(SSH, K_S, H, H_SIG) ->
+ ALG = SSH#ssh.algorithms,
+ case ALG#alg.hkey of
+ 'ssh-rsa' ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ ["ssh-rsa",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = #ssh_key { type=rsa, public={N,E} },
+ case catch ssh_rsa:verify(Public, H, SIG) of
+ {'EXIT', Reason} ->
+ error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
+ {error, bad_signature};
+ ok ->
+ known_host_key(SSH, Public, "ssh-rsa")
+ end;
+ _ ->
+ {error, bad_format}
+ end;
+ 'ssh-dss' ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ ["ssh-dss",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = #ssh_key { type=dsa, public={P,Q,G,Y} },
+ case catch ssh_dsa:verify(Public, H, SIG) of
+ {'EXIT', Reason} ->
+ error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
+ {error, bad_signature};
+ ok ->
+ known_host_key(SSH, Public, "ssh-dss")
+ end;
+ _ ->
+ {error, bad_host_key_format}
+ end;
+ _ ->
+ {error, bad_host_key_algorithm}
+ end.
+
+accepted_host(Ssh, PeerName, Opts) ->
+ case proplists:get_value(silently_accept_hosts, Opts, false) of
+ true ->
+ yes;
+ false ->
+ yes_no(Ssh, "New host " ++ PeerName ++ " accept")
+ end.
+
+known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = Peer} = Ssh,
+ Public, Alg) ->
+ PeerName = peer_name(Peer),
+ case Mod:lookup_host_key(PeerName, Alg, Opts) of
+ {ok, Public} ->
+ ok;
+ {ok, BadPublic} ->
+ error_logger:format("known_host_key: Public ~p BadPublic ~p\n",
+ [Public, BadPublic]),
+ {error, bad_public_key};
+ {error, not_found} ->
+ case accepted_host(Ssh, PeerName, Opts) of
+ yes ->
+ Mod:add_host_key(PeerName, Public, Opts);
+ no ->
+ {error, rejected}
+ end
+ end.
+
+
+%% Each of the algorithm strings MUST be a comma-separated list of
+%% algorithm names (see ''Algorithm Naming'' in [SSH-ARCH]). Each
+%% supported (allowed) algorithm MUST be listed in order of preference.
+%%
+%% The first algorithm in each list MUST be the preferred (guessed)
+%% algorithm. Each string MUST contain at least one algorithm name.
+select_algorithm(Role, Client, Server) ->
+ {Encrypt, Decrypt} = select_encrypt_decrypt(Role, Client, Server),
+ {SendMac, RecvMac} = select_send_recv_mac(Role, Client, Server),
+ {Compression, Decompression} =
+ select_compression_decompression(Role, Client, Server),
+
+ C_Lng = select(Client#ssh_msg_kexinit.languages_client_to_server,
+ Server#ssh_msg_kexinit.languages_client_to_server),
+ S_Lng = select(Client#ssh_msg_kexinit.languages_server_to_client,
+ Server#ssh_msg_kexinit.languages_server_to_client),
+ HKey = select_all(Client#ssh_msg_kexinit.server_host_key_algorithms,
+ Server#ssh_msg_kexinit.server_host_key_algorithms),
+ HK = case HKey of
+ [] -> undefined;
+ [HK0|_] -> HK0
+ end,
+ %% Fixme verify Kex against HKey list and algorithms
+
+ Kex = select(Client#ssh_msg_kexinit.kex_algorithms,
+ Server#ssh_msg_kexinit.kex_algorithms),
+
+ Alg = #alg{kex = Kex,
+ hkey = HK,
+ encrypt = Encrypt,
+ decrypt = Decrypt,
+ send_mac = SendMac,
+ recv_mac = RecvMac,
+ compress = Compression,
+ decompress = Decompression,
+ c_lng = C_Lng,
+ s_lng = S_Lng},
+ {ok, Alg}.
+
+select_encrypt_decrypt(client, Client, Server) ->
+ Encrypt =
+ select(Client#ssh_msg_kexinit.encryption_algorithms_client_to_server,
+ Server#ssh_msg_kexinit.encryption_algorithms_client_to_server),
+ Decrypt =
+ select(Client#ssh_msg_kexinit.encryption_algorithms_server_to_client,
+ Server#ssh_msg_kexinit.encryption_algorithms_server_to_client),
+ {Encrypt, Decrypt};
+select_encrypt_decrypt(server, Client, Server) ->
+ Decrypt =
+ select(Client#ssh_msg_kexinit.encryption_algorithms_client_to_server,
+ Server#ssh_msg_kexinit.encryption_algorithms_client_to_server),
+ Encrypt =
+ select(Client#ssh_msg_kexinit.encryption_algorithms_server_to_client,
+ Server#ssh_msg_kexinit.encryption_algorithms_server_to_client),
+ {Encrypt, Decrypt}.
+
+select_send_recv_mac(client, Client, Server) ->
+ SendMac = select(Client#ssh_msg_kexinit.mac_algorithms_client_to_server,
+ Server#ssh_msg_kexinit.mac_algorithms_client_to_server),
+ RecvMac = select(Client#ssh_msg_kexinit.mac_algorithms_server_to_client,
+ Server#ssh_msg_kexinit.mac_algorithms_server_to_client),
+ {SendMac, RecvMac};
+select_send_recv_mac(server, Client, Server) ->
+ RecvMac = select(Client#ssh_msg_kexinit.mac_algorithms_client_to_server,
+ Server#ssh_msg_kexinit.mac_algorithms_client_to_server),
+ SendMac = select(Client#ssh_msg_kexinit.mac_algorithms_server_to_client,
+ Server#ssh_msg_kexinit.mac_algorithms_server_to_client),
+ {SendMac, RecvMac}.
+
+select_compression_decompression(client, Client, Server) ->
+ Compression =
+ select(Client#ssh_msg_kexinit.compression_algorithms_client_to_server,
+ Server#ssh_msg_kexinit.compression_algorithms_client_to_server),
+ Decomprssion =
+ select(Client#ssh_msg_kexinit.compression_algorithms_server_to_client,
+ Server#ssh_msg_kexinit.compression_algorithms_server_to_client),
+ {Compression, Decomprssion};
+select_compression_decompression(server, Client, Server) ->
+ Decomprssion =
+ select(Client#ssh_msg_kexinit.compression_algorithms_client_to_server,
+ Server#ssh_msg_kexinit.compression_algorithms_client_to_server),
+ Compression =
+ select(Client#ssh_msg_kexinit.compression_algorithms_server_to_client,
+ Server#ssh_msg_kexinit.compression_algorithms_server_to_client),
+ {Compression, Decomprssion}.
+
+install_alg(SSH) ->
+ SSH1 = alg_final(SSH),
+ SSH2 = alg_setup(SSH1),
+ alg_init(SSH2).
+
+alg_setup(SSH) ->
+ ALG = SSH#ssh.algorithms,
+ %%?dbg(?DBG_ALG, "ALG: setup ~p ~n", [ALG]),
+ SSH#ssh{kex = ALG#alg.kex,
+ hkey = ALG#alg.hkey,
+ encrypt = ALG#alg.encrypt,
+ decrypt = ALG#alg.decrypt,
+ send_mac = ALG#alg.send_mac,
+ send_mac_size = mac_digest_size(ALG#alg.send_mac),
+ recv_mac = ALG#alg.recv_mac,
+ recv_mac_size = mac_digest_size(ALG#alg.recv_mac),
+ compress = ALG#alg.compress,
+ decompress = ALG#alg.decompress,
+ c_lng = ALG#alg.c_lng,
+ s_lng = ALG#alg.s_lng,
+ algorithms = undefined
+ }.
+
+alg_init(SSH0) ->
+ %%?dbg(?DBG_ALG, "ALG: init~n", []),
+ {ok,SSH1} = send_mac_init(SSH0),
+ {ok,SSH2} = recv_mac_init(SSH1),
+ {ok,SSH3} = encrypt_init(SSH2),
+ {ok,SSH4} = decrypt_init(SSH3),
+ {ok,SSH5} = compress_init(SSH4),
+ {ok,SSH6} = decompress_init(SSH5),
+ SSH6.
+
+alg_final(SSH0) ->
+ %%?dbg(?DBG_ALG, "ALG: final ~n", []),
+ {ok,SSH1} = send_mac_final(SSH0),
+ {ok,SSH2} = recv_mac_final(SSH1),
+ {ok,SSH3} = encrypt_final(SSH2),
+ {ok,SSH4} = decrypt_final(SSH3),
+ {ok,SSH5} = compress_final(SSH4),
+ {ok,SSH6} = decompress_final(SSH5),
+ SSH6.
+
+select_all(CL, SL) ->
+ A = CL -- SL, %% algortihms only used by client
+ %% algorithms used by client and server (client pref)
+ lists:map(fun(ALG) -> list_to_atom(ALG) end, (CL -- A)).
+
+select([], []) ->
+ none;
+select(CL, SL) ->
+ C = case select_all(CL,SL) of
+ [] -> undefined;
+ [ALG|_] -> ALG
+ end,
+ %%?dbg(?DBG_ALG, "ALG: select: ~p ~p = ~p~n", [CL, SL, C]),
+ C.
+
+ssh_packet(#ssh_msg_kexinit{} = Msg, Ssh0) ->
+ BinMsg = ssh_bits:encode(Msg),
+ Ssh = key_init(Ssh0#ssh.role, Ssh0, BinMsg),
+ %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
+ pack(BinMsg, Ssh);
+
+ssh_packet(Msg, Ssh) ->
+ BinMsg = ssh_bits:encode(Msg),
+ %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
+ %%?dbg(?DBG_BIN_MESSAGE, "Encoded: ~p~n", [BinMsg]),
+ pack(BinMsg, Ssh).
+
+pack(Data0, #ssh{encrypt_block_size = BlockSize,
+ send_sequence = SeqNum, send_mac = MacAlg,
+ send_mac_key = MacKey}
+ = Ssh0) when is_binary(Data0) ->
+ {Ssh1, Data} = compress(Ssh0, Data0),
+ PL = (BlockSize - ((4 + 1 + size(Data)) rem BlockSize)) rem BlockSize,
+ PaddingLen = if PL < 4 -> PL + BlockSize;
+ true -> PL
+ end,
+ Padding = ssh_bits:random(PaddingLen),
+ PacketLen = 1 + PaddingLen + size(Data),
+ PacketData = <<?UINT32(PacketLen),?BYTE(PaddingLen),
+ Data/binary, Padding/binary>>,
+ {Ssh2, EncPacket} = encrypt(Ssh1, PacketData),
+ MAC = mac(MacAlg, MacKey, SeqNum, PacketData),
+ Packet = [EncPacket, MAC],
+ Ssh = Ssh2#ssh{send_sequence = (SeqNum+1) band 16#ffffffff},
+ {Packet, Ssh}.
+
+unpack(EncodedSoFar, ReminingLenght, #ssh{recv_mac_size = MacSize} = Ssh0) ->
+ SshLength = ReminingLenght - MacSize,
+ {NoMac, Mac, Rest} = case MacSize of
+ 0 ->
+ <<NoMac0:SshLength/binary,
+ Rest0/binary>> = EncodedSoFar,
+ {NoMac0, <<>>, Rest0};
+ _ ->
+ <<NoMac0:SshLength/binary,
+ Mac0:MacSize/binary,
+ Rest0/binary>> = EncodedSoFar,
+ {NoMac0, Mac0, Rest0}
+ end,
+ {Ssh1, DecData, <<>>} =
+ case SshLength of
+ 0 ->
+ {Ssh0, <<>>, <<>>};
+ _ ->
+ decrypt_blocks(NoMac, SshLength, Ssh0)
+ end,
+ {Ssh1, DecData, Rest, Mac}.
+
+msg_data(PacketData) ->
+ <<Len:32, PaddingLen:8, _/binary>> = PacketData,
+ DataLen = Len - PaddingLen - 1,
+ <<_:32, _:8, Data:DataLen/binary,
+ _:PaddingLen/binary>> = PacketData,
+ Data.
+
+
+%% Send a disconnect message
+%% terminate(S, SSH, Code, Message) ->
+%% M = #ssh_msg_disconnect{code=Code,
+%% description = Message,
+%% language = "en"},
+%% send_msg(S, SSH, M),
+%% gen_tcp:close(S),
+%% {error, M}.
+
+
+%% public key algorithms
+%%
+%% ssh-dss REQUIRED sign Raw DSS Key
+%% ssh-rsa RECOMMENDED sign Raw RSA Key
+%% x509v3-sign-rsa OPTIONAL sign X.509 certificates (RSA key)
+%% x509v3-sign-dss OPTIONAL sign X.509 certificates (DSS key)
+%% spki-sign-rsa OPTIONAL sign SPKI certificates (RSA key)
+%% spki-sign-dss OPTIONAL sign SPKI certificates (DSS key)
+%% pgp-sign-rsa OPTIONAL sign OpenPGP certificates (RSA key)
+%% pgp-sign-dss OPTIONAL sign OpenPGP certificates (DSS key)
+%%
+
+%% key exchange
+%%
+%% diffie-hellman-group1-sha1 REQUIRED
+%%
+%%
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encryption
+%%
+%% chiphers
+%%
+%% 3des-cbc REQUIRED
+%% three-key 3DES in CBC mode
+%% blowfish-cbc OPTIONAL Blowfish in CBC mode
+%% twofish256-cbc OPTIONAL Twofish in CBC mode,
+%% with 256-bit key
+%% twofish-cbc OPTIONAL alias for "twofish256-cbc" (this
+%% is being retained for
+%% historical reasons)
+%% twofish192-cbc OPTIONAL Twofish with 192-bit key
+%% twofish128-cbc OPTIONAL Twofish with 128-bit key
+%% aes256-cbc OPTIONAL AES in CBC mode,
+%% with 256-bit key
+%% aes192-cbc OPTIONAL AES with 192-bit key
+%% aes128-cbc RECOMMENDED AES with 128-bit key
+%% serpent256-cbc OPTIONAL Serpent in CBC mode, with
+%% 256-bit key
+%% serpent192-cbc OPTIONAL Serpent with 192-bit key
+%% serpent128-cbc OPTIONAL Serpent with 128-bit key
+%% arcfour OPTIONAL the ARCFOUR stream cipher
+%% idea-cbc OPTIONAL IDEA in CBC mode
+%% cast128-cbc OPTIONAL CAST-128 in CBC mode
+%% none OPTIONAL no encryption; NOT RECOMMENDED
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encrypt_init(#ssh{encrypt = none} = Ssh) ->
+ {ok, Ssh};
+encrypt_init(#ssh{encrypt = '3des-cbc', role = client} = Ssh) ->
+ IV = hash(Ssh, "A", 64),
+ <<K1:8/binary, K2:8/binary, K3:8/binary>> = hash(Ssh, "C", 192),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2,K3},
+ encrypt_block_size = 8,
+ encrypt_ctx = IV}};
+encrypt_init(#ssh{encrypt = '3des-cbc', role = server} = Ssh) ->
+ IV = hash(Ssh, "B", 64),
+ <<K1:8/binary, K2:8/binary, K3:8/binary>> = hash(Ssh, "D", 192),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2,K3},
+ encrypt_block_size = 8,
+ encrypt_ctx = IV}};
+encrypt_init(#ssh{encrypt = 'aes128-cbc', role = client} = Ssh) ->
+ IV = hash(Ssh, "A", 128),
+ <<K:16/binary>> = hash(Ssh, "C", 128),
+ {ok, Ssh#ssh{encrypt_keys = K,
+ encrypt_block_size = 16,
+ encrypt_ctx = IV}};
+encrypt_init(#ssh{encrypt = 'aes128-cbc', role = server} = Ssh) ->
+ IV = hash(Ssh, "B", 128),
+ <<K:16/binary>> = hash(Ssh, "D", 128),
+ {ok, Ssh#ssh{encrypt_keys = K,
+ encrypt_block_size = 16,
+ encrypt_ctx = IV}}.
+
+encrypt_final(Ssh) ->
+ {ok, Ssh#ssh{encrypt = none,
+ encrypt_keys = undefined,
+ encrypt_block_size = 8,
+ encrypt_ctx = undefined
+ }}.
+
+encrypt(#ssh{encrypt = none} = Ssh, Data) ->
+ {Ssh, Data};
+encrypt(#ssh{encrypt = '3des-cbc',
+ encrypt_keys = {K1,K2,K3},
+ encrypt_ctx = IV0} = Ssh, Data) ->
+ %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
+ %% [IV0,K1,K2,K3]),
+ Enc = crypto:des3_cbc_encrypt(K1,K2,K3,IV0,Data),
+ %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
+ IV = crypto:des_cbc_ivec(Enc),
+ {Ssh#ssh{encrypt_ctx = IV}, Enc};
+encrypt(#ssh{encrypt = 'aes128-cbc',
+ encrypt_keys = K,
+ encrypt_ctx = IV0} = Ssh, Data) ->
+ %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K=~p ~n",
+ %% [IV0,K]),
+ Enc = crypto:aes_cbc_128_encrypt(K,IV0,Data),
+ %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
+ IV = crypto:aes_cbc_ivec(Enc),
+ {Ssh#ssh{encrypt_ctx = IV}, Enc}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Decryption
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+decrypt_init(#ssh{decrypt = none} = Ssh) ->
+ {ok, Ssh};
+decrypt_init(#ssh{decrypt = '3des-cbc', role = client} = Ssh) ->
+ {IV, KD} = {hash(Ssh, "B", 64),
+ hash(Ssh, "D", 192)},
+ <<K1:8/binary, K2:8/binary, K3:8/binary>> = KD,
+ {ok, Ssh#ssh{decrypt_keys = {K1,K2,K3}, decrypt_ctx = IV,
+ decrypt_block_size = 8}};
+decrypt_init(#ssh{decrypt = '3des-cbc', role = server} = Ssh) ->
+ {IV, KD} = {hash(Ssh, "A", 64),
+ hash(Ssh, "C", 192)},
+ <<K1:8/binary, K2:8/binary, K3:8/binary>> = KD,
+ {ok, Ssh#ssh{decrypt_keys = {K1, K2, K3}, decrypt_ctx = IV,
+ decrypt_block_size = 8}};
+decrypt_init(#ssh{decrypt = 'aes128-cbc', role = client} = Ssh) ->
+ {IV, KD} = {hash(Ssh, "B", 128),
+ hash(Ssh, "D", 128)},
+ <<K:16/binary>> = KD,
+ {ok, Ssh#ssh{decrypt_keys = K, decrypt_ctx = IV,
+ decrypt_block_size = 16}};
+decrypt_init(#ssh{decrypt = 'aes128-cbc', role = server} = Ssh) ->
+ {IV, KD} = {hash(Ssh, "A", 128),
+ hash(Ssh, "C", 128)},
+ <<K:16/binary>> = KD,
+ {ok, Ssh#ssh{decrypt_keys = K, decrypt_ctx = IV,
+ decrypt_block_size = 16}}.
+
+
+decrypt_final(Ssh) ->
+ {ok, Ssh#ssh {decrypt = none,
+ decrypt_keys = undefined,
+ decrypt_ctx = undefined,
+ decrypt_block_size = 8}}.
+
+decrypt(#ssh{decrypt = none} = Ssh, Data) ->
+ {Ssh, Data};
+decrypt(#ssh{decrypt = '3des-cbc', decrypt_keys = Keys,
+ decrypt_ctx = IV0} = Ssh, Data) ->
+ {K1, K2, K3} = Keys,
+ %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
+ %%[IV0,K1,K2,K3]),
+ Dec = crypto:des3_cbc_decrypt(K1,K2,K3,IV0,Data),
+ %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
+ IV = crypto:des_cbc_ivec(Data),
+ {Ssh#ssh{decrypt_ctx = IV}, Dec};
+decrypt(#ssh{decrypt = 'aes128-cbc', decrypt_keys = Key,
+ decrypt_ctx = IV0} = Ssh, Data) ->
+ %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p Key=~p ~n",
+ %% [IV0,Key]),
+ Dec = crypto:aes_cbc_128_decrypt(Key,IV0,Data),
+ %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
+ IV = crypto:aes_cbc_ivec(Data),
+ {Ssh#ssh{decrypt_ctx = IV}, Dec}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Compression
+%%
+%% none REQUIRED no compression
+%% zlib OPTIONAL ZLIB (LZ77) compression
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+compress_init(SSH) ->
+ compress_init(SSH, 1).
+
+compress_init(#ssh{compress = none} = Ssh, _) ->
+ {ok, Ssh};
+compress_init(#ssh{compress = zlib} = Ssh, Level) ->
+ Zlib = zlib:open(),
+ ok = zlib:deflateInit(Zlib, Level),
+ {ok, Ssh#ssh{compress_ctx = Zlib}}.
+
+
+compress_final(#ssh{compress = none} = Ssh) ->
+ {ok, Ssh};
+compress_final(#ssh{compress = zlib, compress_ctx = Context} = Ssh) ->
+ zlib:close(Context),
+ {ok, Ssh#ssh{compress = none, compress_ctx = undefined}}.
+
+compress(#ssh{compress = none} = Ssh, Data) ->
+ {Ssh, Data};
+compress(#ssh{compress = zlib, compress_ctx = Context} = Ssh, Data) ->
+ Compressed = zlib:deflate(Context, Data, sync),
+ %%?dbg(?DBG_ZLIB, "deflate: ~p -> ~p ~n", [Data, Compressed]),
+ {Ssh, list_to_binary(Compressed)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Decompression
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+decompress_init(#ssh{decompress = none} = Ssh) ->
+ {ok, Ssh};
+decompress_init(#ssh{decompress = zlib} = Ssh) ->
+ Zlib = zlib:open(),
+ ok = zlib:inflateInit(Zlib),
+ {ok, Ssh#ssh{decompress_ctx = Zlib}}.
+
+decompress_final(#ssh{decompress = none} = Ssh) ->
+ {ok, Ssh};
+decompress_final(#ssh{decompress = zlib, decompress_ctx = Context} = Ssh) ->
+ zlib:close(Context),
+ {ok, Ssh#ssh{decompress = none, decompress_ctx = undefined}}.
+
+decompress(#ssh{decompress = none} = Ssh, Data) ->
+ {Ssh, Data};
+decompress(#ssh{decompress = zlib, decompress_ctx = Context} = Ssh, Data) ->
+ Decompressed = zlib:inflate(Context, Data),
+ %%?dbg(?DBG_ZLIB, "inflate: ~p -> ~p ~n", [Data, Decompressed]),
+ {Ssh, list_to_binary(Decompressed)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% MAC calculation
+%%
+%% hmac-sha1 REQUIRED HMAC-SHA1 (digest length = key
+%% length = 20)
+%% hmac-sha1-96 RECOMMENDED first 96 bits of HMAC-SHA1 (digest
+%% length = 12, key length = 20)
+%% hmac-md5 OPTIONAL HMAC-MD5 (digest length = key
+%% length = 16)
+%% hmac-md5-96 OPTIONAL first 96 bits of HMAC-MD5 (digest
+%% length = 12, key length = 16)
+%% none OPTIONAL no MAC; NOT RECOMMENDED
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+send_mac_init(SSH) ->
+ case SSH#ssh.role of
+ client ->
+ KeySize =mac_key_size(SSH#ssh.send_mac),
+ Key = hash(SSH, "E", KeySize),
+ {ok, SSH#ssh { send_mac_key = Key }};
+ server ->
+ KeySize = mac_key_size(SSH#ssh.send_mac),
+ Key = hash(SSH, "F", KeySize),
+ {ok, SSH#ssh { send_mac_key = Key }}
+ end.
+
+send_mac_final(SSH) ->
+ {ok, SSH#ssh { send_mac = none, send_mac_key = undefined }}.
+
+recv_mac_init(SSH) ->
+ case SSH#ssh.role of
+ client ->
+ Key = hash(SSH, "F", mac_key_size(SSH#ssh.recv_mac)),
+ {ok, SSH#ssh { recv_mac_key = Key }};
+ server ->
+ Key = hash(SSH, "E", mac_key_size(SSH#ssh.recv_mac)),
+ {ok, SSH#ssh { recv_mac_key = Key }}
+ end.
+
+recv_mac_final(SSH) ->
+ {ok, SSH#ssh { recv_mac = none, recv_mac_key = undefined }}.
+
+mac(none, _ , _, _) ->
+ <<>>;
+mac('hmac-sha1', Key, SeqNum, Data) ->
+ crypto:sha_mac(Key, [<<?UINT32(SeqNum)>>, Data]);
+mac('hmac-sha1-96', Key, SeqNum, Data) ->
+ crypto:sha_mac_96(Key, [<<?UINT32(SeqNum)>>, Data]);
+mac('hmac-md5', Key, SeqNum, Data) ->
+ crypto:md5_mac(Key, [<<?UINT32(SeqNum)>>, Data]);
+mac('hmac-md5-96', Key, SeqNum, Data) ->
+ crypto:md5_mac_96(Key, [<<?UINT32(SeqNum)>>, Data]).
+
+%% return N hash bytes (HASH)
+hash(SSH, Char, Bits) ->
+ HASH =
+ case SSH#ssh.kex of
+ 'diffie-hellman-group1-sha1' ->
+ fun(Data) -> crypto:sha(Data) end;
+ 'diffie-hellman-group-exchange-sha1' ->
+ fun(Data) -> crypto:sha(Data) end;
+ _ ->
+ exit({bad_algorithm,SSH#ssh.kex})
+ end,
+ hash(SSH, Char, Bits, HASH).
+
+hash(_SSH, _Char, 0, _HASH) ->
+ <<>>;
+hash(SSH, Char, N, HASH) ->
+ K = ssh_bits:mpint(SSH#ssh.shared_secret),
+ H = SSH#ssh.exchanged_hash,
+ SessionID = SSH#ssh.session_id,
+ K1 = HASH([K, H, Char, SessionID]),
+ Sz = N div 8,
+ <<Key:Sz/binary, _/binary>> = hash(K, H, K1, N-128, HASH),
+ %%?dbg(?DBG_KEX, "Key ~s: ~s ~n", [Char, fmt_binary(Key, 16, 4)]),
+ Key.
+
+hash(_K, _H, Ki, N, _HASH) when N =< 0 ->
+ Ki;
+hash(K, H, Ki, N, HASH) ->
+ Kj = HASH([K, H, Ki]),
+ hash(K, H, <<Ki/binary, Kj/binary>>, N-128, HASH).
+
+kex_h(SSH, K_S, E, F, K) ->
+ L = ssh_bits:encode([SSH#ssh.c_version, SSH#ssh.s_version,
+ SSH#ssh.c_keyinit, SSH#ssh.s_keyinit,
+ K_S, E,F,K],
+ [string,string,binary,binary,binary,
+ mpint,mpint,mpint]),
+ crypto:sha(L).
+
+kex_h(SSH, K_S, Min, NBits, Max, Prime, Gen, E, F, K) ->
+ L = if Min==-1; Max==-1 ->
+ Ts = [string,string,binary,binary,binary,
+ uint32,
+ mpint,mpint,mpint,mpint,mpint],
+ ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version,
+ SSH#ssh.c_keyinit,SSH#ssh.s_keyinit,
+ K_S, NBits, Prime, Gen, E,F,K],
+ Ts);
+ true ->
+ Ts = [string,string,binary,binary,binary,
+ uint32,uint32,uint32,
+ mpint,mpint,mpint,mpint,mpint],
+ ssh_bits:encode([SSH#ssh.c_version,SSH#ssh.s_version,
+ SSH#ssh.c_keyinit,SSH#ssh.s_keyinit,
+ K_S, Min, NBits, Max,
+ Prime, Gen, E,F,K], Ts)
+ end,
+ crypto:sha(L).
+
+mac_key_size('hmac-sha1') -> 20*8;
+mac_key_size('hmac-sha1-96') -> 20*8;
+mac_key_size('hmac-md5') -> 16*8;
+mac_key_size('hmac-md5-96') -> 16*8;
+mac_key_size(none) -> 0.
+
+mac_digest_size('hmac-sha1') -> 20;
+mac_digest_size('hmac-sha1-96') -> 12;
+mac_digest_size('hmac-md5') -> 20;
+mac_digest_size('hmac-md5-96') -> 12;
+mac_digest_size(none) -> 0.
+
+peer_name({Host, _}) ->
+ Host.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Diffie-Hellman utils
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+dh_group1() ->
+ {2, 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF}.
+
+dh_gen_key(G, P, _Bits) ->
+ Private = ssh_bits:irandom(ssh_bits:isize(P)-1, 1, 1),
+ Public = ssh_math:ipow(G, Private, P),
+ {Private,Public}.
+
+%% trim(Str) ->
+%% lists:reverse(trim_head(lists:reverse(trim_head(Str)))).
+
+trim_tail(Str) ->
+ lists:reverse(trim_head(lists:reverse(Str))).
+
+trim_head([$\s|Cs]) -> trim_head(Cs);
+trim_head([$\t|Cs]) -> trim_head(Cs);
+trim_head([$\n|Cs]) -> trim_head(Cs);
+trim_head([$\r|Cs]) -> trim_head(Cs);
+trim_head(Cs) -> Cs.
+
+%% Retrieve session_id from ssh, needed by public-key auth
+%get_session_id(SSH) ->
+% {ok, SessionID} = call(SSH, get_session_id),
+
+%% DEBUG utils
+%% Format integers and binaries as hex blocks
+%%
+%% -ifdef(debug).
+%% fmt_binary(B, BlockSize, GroupSize) ->
+%% fmt_block(fmt_bin(B), BlockSize, GroupSize).
+
+%% fmt_block(Bin, BlockSize, GroupSize) ->
+%% fmt_block(Bin, BlockSize, 0, GroupSize).
+
+
+%% fmt_block(Bin, 0, _I, _G) ->
+%% binary_to_list(Bin);
+%% fmt_block(Bin, Sz, G, G) when G =/= 0 ->
+%% ["~n#" | fmt_block(Bin, Sz, 0, G)];
+%% fmt_block(Bin, Sz, I, G) ->
+%% case Bin of
+%% <<Block:Sz/binary, Tail/binary>> ->
+%% if Tail == <<>> ->
+%% [binary_to_list(Block)];
+%% true ->
+%% [binary_to_list(Block), " " | fmt_block(Tail, Sz, I+1, G)]
+%% end;
+%% <<>> ->
+%% [];
+%% _ ->
+%% [binary_to_list(Bin)]
+%% end.
+
+%% %% Format integer or binary as hex
+%% fmt_bin(X) when integer(X) ->
+%% list_to_binary(io_lib:format("~p", [X]));
+%% fmt_bin(X) when binary(X) ->
+%% Sz = size(X)*8,
+%% <<Y:Sz/unsigned-big>> = X,
+%% %%Fmt = "~"++integer_to_list(size(X)*2)++"~p",
+%% list_to_binary(io_lib:format("~p", [Y])).
+
+%% -endif.
+
diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl
new file mode 100644
index 0000000000..18a23f0533
--- /dev/null
+++ b/lib/ssh/src/ssh_transport.hrl
@@ -0,0 +1,235 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Record and constant defenitions for the SSH-tansport layer
+%% protocol see RFC 4253
+%%----------------------------------------------------------------------
+
+-ifndef(ssh_transport).
+-define(ssh_transport, true).
+
+-define(DEFAULT_CLIENT_VERSION, {2, 0}).
+-define(DEFAULT_SERVER_VERSION, {2, 0}).
+-define(DEFAULT_DH_GROUP_MIN, 512).
+-define(DEFAULT_DH_GROUP_NBITS, 1024).
+-define(DEFAULT_DH_GROUP_MAX, 4096).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% BASIC transport messages
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(SSH_MSG_DISCONNECT, 1).
+-define(SSH_MSG_IGNORE, 2).
+-define(SSH_MSG_UNIMPLEMENTED, 3).
+-define(SSH_MSG_DEBUG, 4).
+-define(SSH_MSG_SERVICE_REQUEST, 5).
+-define(SSH_MSG_SERVICE_ACCEPT, 6).
+
+-define(SSH_MSG_KEXINIT, 20).
+-define(SSH_MSG_NEWKEYS, 21).
+
+
+-record(ssh_msg_disconnect,
+ {
+ code, %% uint32
+ description, %% string
+ language %% string
+ }).
+
+-record(ssh_msg_ignore,
+ {
+ data %% string
+ }).
+
+-record(ssh_msg_unimplemented,
+ {
+ sequence %% uint32
+ }).
+
+-record(ssh_msg_debug,
+ {
+ always_display, %% boolean
+ message, %% string
+ language %% string
+ }).
+
+
+-record(ssh_msg_service_request,
+ {
+ name %% string (service name)
+ }).
+
+-record(ssh_msg_service_accept,
+ {
+ name %% string
+ }).
+
+-record(ssh_msg_kexinit,
+ {
+ cookie, %% random(16)
+ kex_algorithms, %% string
+ server_host_key_algorithms, %% string
+ encryption_algorithms_client_to_server, %% string
+ encryption_algorithms_server_to_client, %% string
+ mac_algorithms_client_to_server, %% string
+ mac_algorithms_server_to_client, %% string
+ compression_algorithms_client_to_server, %% string
+ compression_algorithms_server_to_client, %% string
+ languages_client_to_server, %% string
+ languages_server_to_client, %% string
+ first_kex_packet_follows=false, %% boolean
+ %% (reserved for future extension)
+ reserved=0 %% uint32=0
+ }).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% KEY DH messages
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% diffie-hellman-group1-sha1
+-define(SSH_MSG_KEXDH_INIT, 30).
+-define(SSH_MSG_KEXDH_REPLY, 31).
+
+-record(ssh_msg_kexdh_init,
+ {
+ e %% mpint
+ }).
+
+-record(ssh_msg_kexdh_reply,
+ {
+ public_host_key, %% string (K_S)
+ f, %% mpint
+ h_sig %% string, signature of H
+ }).
+
+-record(ssh_msg_newkeys,
+ {}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% KEY DH GEX messages
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% diffie-hellman-group-exchange-sha1
+-define(SSH_MSG_KEX_DH_GEX_REQUEST_OLD, 30).
+-define(SSH_MSG_KEX_DH_GEX_REQUEST, 34).
+-define(SSH_MSG_KEX_DH_GEX_GROUP, 31).
+-define(SSH_MSG_KEX_DH_GEX_INIT, 32).
+-define(SSH_MSG_KEX_DH_GEX_REPLY, 33).
+
+-record(ssh_msg_kex_dh_gex_request,
+ {
+ min,
+ n,
+ max
+ }).
+
+-record(ssh_msg_kex_dh_gex_request_old,
+ {
+ n
+ }).
+
+-record(ssh_msg_kex_dh_gex_group,
+ {
+ p, %% prime
+ g %% generator
+ }).
+
+-record(ssh_msg_kex_dh_gex_init,
+ {
+ e
+ }).
+
+-record(ssh_msg_kex_dh_gex_reply,
+ {
+ public_host_key, %% string (K_S)
+ f,
+ h_sig
+ }).
+
+%% error codes
+-define(SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, 1).
+-define(SSH_DISCONNECT_PROTOCOL_ERROR, 2).
+-define(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 3).
+-define(SSH_DISCONNECT_RESERVED, 4).
+-define(SSH_DISCONNECT_MAC_ERROR, 5).
+-define(SSH_DISCONNECT_COMPRESSION_ERROR, 6).
+-define(SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, 7).
+-define(SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, 8).
+-define(SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE, 9).
+-define(SSH_DISCONNECT_CONNECTION_LOST, 10).
+-define(SSH_DISCONNECT_BY_APPLICATION, 11).
+-define(SSH_DISCONNECT_TOO_MANY_CONNECTIONS, 12).
+-define(SSH_DISCONNECT_AUTH_CANCELLED_BY_USER, 13).
+-define(SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, 14).
+-define(SSH_DISCONNECT_ILLEGAL_USER_NAME, 15).
+
+
+%%%----------------------------------------------------------------------
+%%% # DH_14_xxx
+%%% Description: Oakley group 14 prime numbers and generator. Used in
+%%% diffie-hellman-group1-sha1 key exchange method.
+%%%----------------------------------------------------------------------
+%%%----------------------------------------------------------------------
+%%% # DH_14_P
+%%% Description: Prime for this group
+%%%----------------------------------------------------------------------
+
+-define(DH_14_P,
+ <<000,000,000,129,000,255,255,255,255,255,255,255,255,201,015,218,
+ 162,033,104,194,052,196,198,098,139,128,220,028,209,041,002,078,
+ 008,138,103,204,116,002,011,190,166,059,019,155,034,081,074,008,
+ 121,142,052,004,221,239,149,025,179,205,058,067,027,048,043,010,
+ 109,242,095,020,055,079,225,053,109,109,081,194,069,228,133,181,
+ 118,098,094,126,198,244,076,066,233,166,055,237,107,011,255,092,
+ 182,244,006,183,237,238,056,107,251,090,137,159,165,174,159,036,
+ 017,124,075,031,230,073,040,102,081,236,230,083,129,255,255,255,
+ 255,255,255,255,255>>).
+
+%%%----------------------------------------------------------------------
+%%% # DH_14_G
+%%% Description: Generator for DH_14_P.
+%%%----------------------------------------------------------------------
+
+-define(DH_14_G, <<0,0,0,1,2>>).
+
+%%%----------------------------------------------------------------------
+%%% # DH_14_Q
+%%% Description: Group order (DH_14_P - 1) / 2.
+%%%----------------------------------------------------------------------
+
+-define(DH_14_Q,
+ <<000,000,000,128,127,255,255,255,255,255,255,255,228,135,237,081,
+ 016,180,097,026,098,099,049,069,192,110,014,104,148,129,039,004,
+ 069,051,230,058,001,005,223,083,029,137,205,145,040,165,004,060,
+ 199,026,002,110,247,202,140,217,230,157,033,141,152,021,133,054,
+ 249,047,138,027,167,240,154,182,182,168,225,034,242,066,218,187,
+ 049,047,063,099,122,038,033,116,211,027,246,181,133,255,174,091,
+ 122,003,091,246,247,028,053,253,173,068,207,210,215,079,146,008,
+ 190,037,143,243,036,148,051,040,246,115,041,192,255,255,255,255,
+ 255,255,255,255>>).
+
+-endif. % -ifdef(ssh_transport).
diff --git a/lib/ssh/src/ssh_userauth.hrl b/lib/ssh/src/ssh_userauth.hrl
new file mode 100755
index 0000000000..39cc032ca5
--- /dev/null
+++ b/lib/ssh/src/ssh_userauth.hrl
@@ -0,0 +1,77 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: user authentication protocol
+
+-define(SSH_MSG_USERAUTH_REQUEST, 50).
+-define(SSH_MSG_USERAUTH_FAILURE, 51).
+-define(SSH_MSG_USERAUTH_SUCCESS, 52).
+-define(SSH_MSG_USERAUTH_BANNER, 53).
+-define(SSH_MSG_USERAUTH_PK_OK, 60).
+-define(SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 60).
+-define(SSH_MSG_USERAUTH_INFO_REQUEST, 60).
+-define(SSH_MSG_USERAUTH_INFO_RESPONSE, 61).
+
+-record(ssh_msg_userauth_request,
+ {
+ user, %% string
+ service, %% string
+ method, %% string "publickey", "password"
+ data %% opaque
+ }).
+
+-record(ssh_msg_userauth_failure,
+ {
+ authentications, %% string
+ partial_success %% boolean
+ }).
+
+-record(ssh_msg_userauth_success,
+ {
+ }).
+
+-record(ssh_msg_userauth_banner,
+ {
+ message, %% string
+ language %% string
+ }).
+
+-record(ssh_msg_userauth_passwd_changereq,
+ {
+ prompt, %% string
+ languge %% string
+ }).
+
+-record(ssh_msg_userauth_pk_ok,
+ {
+ algorithm_name, % string
+ key_blob % string
+ }).
+
+-record(ssh_msg_userauth_info_request,
+ {name,
+ instruction,
+ language_tag,
+ num_prompts,
+ data}).
+-record(ssh_msg_userauth_info_response,
+ {num_responses,
+ data}).
diff --git a/lib/ssh/src/ssh_userreg.erl b/lib/ssh/src/ssh_userreg.erl
new file mode 100644
index 0000000000..06f4076b51
--- /dev/null
+++ b/lib/ssh/src/ssh_userreg.erl
@@ -0,0 +1,127 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Description: User register for ssh_cli
+
+-module(ssh_userreg).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0, register_user/2, lookup_user/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-record(state, {user_db = []}).
+
+%%====================================================================
+%% API
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+register_user(User, Cm) ->
+ gen_server:cast(?MODULE, {register, {User, Cm}}).
+
+lookup_user(Cm) ->
+ gen_server:call(?MODULE, {get_user, Cm}, infinity).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init([]) ->
+ {ok, #state{}}.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+handle_call({get_user, Cm}, _From, #state{user_db = Db} = State) ->
+ User = lookup(Cm, Db),
+ {reply, {ok, User}, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast({register, UserCm}, State0) ->
+ State = insert(UserCm, State0),
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+insert({User, Cm}, #state{user_db = Db} = State) ->
+ State#state{user_db = [{User, Cm} | Db]}.
+
+lookup(_, []) ->
+ undefined;
+lookup(Cm, [{User, Cm} | _Rest]) ->
+ User;
+lookup(Cm, [_ | Rest]) ->
+ lookup(Cm, Rest).
+
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
new file mode 100644
index 0000000000..a347a9c095
--- /dev/null
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -0,0 +1,925 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: SFTP functions
+
+-module(ssh_xfer).
+
+-export([attach/2, connect/3]).
+-export([open/6, opendir/3, readdir/3, close/3, read/5, write/5,
+ rename/5, remove/3, mkdir/4, rmdir/3, realpath/3, extended/4,
+ stat/4, fstat/4, lstat/4, setstat/4,
+ readlink/3, fsetstat/4, symlink/4,
+ protocol_version_request/1,
+ xf_reply/2,
+ xf_send_reply/3, xf_send_names/3, xf_send_name/4,
+ xf_send_status/3, xf_send_status/4, xf_send_status/5,
+ xf_send_handle/3, xf_send_attr/3, xf_send_data/3,
+ encode_erlang_status/1,
+ decode_open_flags/2, encode_open_flags/1,
+ decode_ace_mask/1, decode_ext/1,
+ decode_ATTR/2, encode_ATTR/2]).
+
+-include("ssh.hrl").
+-include("ssh_xfer.hrl").
+
+-import(lists, [foldl/3, reverse/1]).
+
+-define(is_set(F, Bits),
+ ((F) band (Bits)) == (F)).
+
+-define(XFER_PACKET_SIZE, 32768).
+-define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE).
+
+attach(CM, Opts) ->
+ open_xfer(CM, Opts).
+
+connect(Host, Port, Opts) ->
+ case ssh:connect(Host, Port, Opts) of
+ {ok, CM} -> open_xfer(CM, Opts);
+ Error -> Error
+ end.
+
+open_xfer(CM, Opts) ->
+ TMO = proplists:get_value(timeout, Opts, infinity),
+ case ssh_connection:session_channel(CM, ?XFER_WINDOW_SIZE, ?XFER_PACKET_SIZE, TMO) of
+ {ok, ChannelId} ->
+ {ok, ChannelId, CM};
+ Error ->
+ Error
+ end.
+
+protocol_version_request(XF) ->
+ xf_request(XF, ?SSH_FXP_INIT, <<?UINT32(?SSH_SFTP_PROTOCOL_VERSION)>>).
+
+open(XF, ReqID, FileName, Access, Flags, Attrs) ->
+ Vsn = XF#ssh_xfer.vsn,
+ FileName1 = list_to_binary(FileName),
+ MBits = if Vsn >= 5 ->
+ M = encode_ace_mask(Access),
+ ?uint32(M);
+ true ->
+ (<<>>)
+ end,
+ F = encode_open_flags(Flags),
+ xf_request(XF,?SSH_FXP_OPEN,
+ [?uint32(ReqID),
+ ?binary(FileName1),
+ MBits,
+ ?uint32(F),
+ encode_ATTR(Vsn,Attrs)]).
+
+opendir(XF, ReqID, DirName) ->
+ xf_request(XF, ?SSH_FXP_OPENDIR,
+ [?uint32(ReqID),
+ ?string(DirName)]).
+
+
+close(XF, ReqID, Handle) ->
+ xf_request(XF, ?SSH_FXP_CLOSE,
+ [?uint32(ReqID),
+ ?binary(Handle)]).
+
+read(XF, ReqID, Handle, Offset, Length) ->
+ xf_request(XF, ?SSH_FXP_READ,
+ [?uint32(ReqID),
+ ?binary(Handle),
+ ?uint64(Offset),
+ ?uint32(Length)]).
+
+readdir(XF, ReqID, Handle) ->
+ xf_request(XF, ?SSH_FXP_READDIR,
+ [?uint32(ReqID),
+ ?binary(Handle)]).
+
+write(XF,ReqID, Handle, Offset, Data) ->
+ Data1 = if
+ is_binary(Data) ->
+ Data;
+ is_list(Data) ->
+ list_to_binary(Data)
+ end,
+ xf_request(XF,?SSH_FXP_WRITE,
+ [?uint32(ReqID),
+ ?binary(Handle),
+ ?uint64(Offset),
+ ?binary(Data1)]).
+
+%% Remove a file
+remove(XF, ReqID, File) ->
+ xf_request(XF, ?SSH_FXP_REMOVE,
+ [?uint32(ReqID),
+ ?string(File)]).
+
+%% Rename a file/directory
+rename(XF, ReqID, Old, New, Flags) ->
+ Vsn = XF#ssh_xfer.vsn,
+ OldPath = list_to_binary(Old),
+ NewPath = list_to_binary(New),
+ FlagBits
+ = if Vsn >= 5 ->
+ F0 = encode_rename_flags(Flags),
+ ?uint32(F0);
+ true ->
+ (<<>>)
+ end,
+ xf_request(XF, ?SSH_FXP_RENAME,
+ [?uint32(ReqID),
+ ?binary(OldPath),
+ ?binary(NewPath),
+ FlagBits]).
+
+
+
+%% Create directory
+mkdir(XF, ReqID, Path, Attrs) ->
+ Path1 = list_to_binary(Path),
+ xf_request(XF, ?SSH_FXP_MKDIR,
+ [?uint32(ReqID),
+ ?binary(Path1),
+ encode_ATTR(XF#ssh_xfer.vsn, Attrs)]).
+
+%% Remove a directory
+rmdir(XF, ReqID, Dir) ->
+ Dir1 = list_to_binary(Dir),
+ xf_request(XF, ?SSH_FXP_RMDIR,
+ [?uint32(ReqID),
+ ?binary(Dir1)]).
+
+%% Stat file
+stat(XF, ReqID, Path, Flags) ->
+ Path1 = list_to_binary(Path),
+ Vsn = XF#ssh_xfer.vsn,
+ AttrFlags = if Vsn >= 5 ->
+ F = encode_attr_flags(Vsn, Flags),
+ ?uint32(F);
+ true ->
+ []
+ end,
+ xf_request(XF, ?SSH_FXP_STAT,
+ [?uint32(ReqID),
+ ?binary(Path1),
+ AttrFlags]).
+
+
+%% Stat file - follow symbolic links
+lstat(XF, ReqID, Path, Flags) ->
+ Path1 = list_to_binary(Path),
+ Vsn = XF#ssh_xfer.vsn,
+ AttrFlags = if Vsn >= 5 ->
+ F = encode_attr_flags(Vsn, Flags),
+ ?uint32(F);
+ true ->
+ []
+ end,
+ xf_request(XF, ?SSH_FXP_LSTAT,
+ [?uint32(ReqID),
+ ?binary(Path1),
+ AttrFlags]).
+
+%% Stat open file
+fstat(XF, ReqID, Handle, Flags) ->
+ Vsn = XF#ssh_xfer.vsn,
+ AttrFlags = if Vsn >= 5 ->
+ F = encode_attr_flags(Vsn, Flags),
+ ?uint32(F);
+ true ->
+ []
+ end,
+ xf_request(XF, ?SSH_FXP_FSTAT,
+ [?uint32(ReqID),
+ ?binary(Handle),
+ AttrFlags]).
+
+%% Modify file attributes
+setstat(XF, ReqID, Path, Attrs) ->
+ Path1 = list_to_binary(Path),
+ xf_request(XF, ?SSH_FXP_SETSTAT,
+ [?uint32(ReqID),
+ ?binary(Path1),
+ encode_ATTR(XF#ssh_xfer.vsn, Attrs)]).
+
+
+%% Modify file attributes
+fsetstat(XF, ReqID, Handle, Attrs) ->
+ xf_request(XF, ?SSH_FXP_FSETSTAT,
+ [?uint32(ReqID),
+ ?binary(Handle),
+ encode_ATTR(XF#ssh_xfer.vsn, Attrs)]).
+
+%% Read a symbolic link
+readlink(XF, ReqID, Path) ->
+ Path1 = list_to_binary(Path),
+ xf_request(XF, ?SSH_FXP_READLINK,
+ [?uint32(ReqID),
+ ?binary(Path1)]).
+
+
+%% Create a symbolic link
+symlink(XF, ReqID, LinkPath, TargetPath) ->
+ LinkPath1 = list_to_binary(LinkPath),
+ TargetPath1 = list_to_binary(TargetPath),
+ xf_request(XF, ?SSH_FXP_SYMLINK,
+ [?uint32(ReqID),
+ ?binary(LinkPath1),
+ ?binary(TargetPath1)]).
+
+%% Convert a path into a 'canonical' form
+realpath(XF, ReqID, Path) ->
+ Path1 = list_to_binary(Path),
+ xf_request(XF, ?SSH_FXP_REALPATH,
+ [?uint32(ReqID),
+ ?binary(Path1)]).
+
+extended(XF, ReqID, Request, Data) ->
+ xf_request(XF, ?SSH_FXP_EXTENDED,
+ [?uint32(ReqID),
+ ?string(Request),
+ ?binary(Data)]).
+
+
+%% Send xfer request to connection manager
+xf_request(XF, Op, Arg) ->
+ CM = XF#ssh_xfer.cm,
+ Channel = XF#ssh_xfer.channel,
+ Data = if
+ is_binary(Arg) ->
+ Arg;
+ is_list(Arg) ->
+ list_to_binary(Arg)
+ end,
+ Size = 1+size(Data),
+ ssh_connection:send(CM, Channel, <<?UINT32(Size), Op, Data/binary>>).
+
+xf_send_reply(#ssh_xfer{cm = CM, channel = Channel}, Op, Arg) ->
+ Data = if
+ is_binary(Arg) ->
+ Arg;
+ is_list(Arg) ->
+ list_to_binary(Arg)
+ end,
+ Size = 1 + size(Data),
+ ssh_connection:send(CM, Channel, <<?UINT32(Size), Op, Data/binary>>).
+
+xf_send_name(XF, ReqId, Name, Attr) ->
+ xf_send_names(XF, ReqId, [{Name, Attr}]).
+
+
+xf_send_handle(#ssh_xfer{cm = CM, channel = Channel},
+ ReqId, Handle) ->
+ HLen = length(Handle),
+ Size = 1 + 4 + 4+HLen,
+ ToSend = [<<?UINT32(Size), ?SSH_FXP_HANDLE, ?UINT32(ReqId), ?UINT32(HLen)>>,
+ Handle],
+ ssh_connection:send(CM, Channel, ToSend).
+
+xf_send_names(#ssh_xfer{cm = CM, channel = Channel, vsn = Vsn},
+ ReqId, NamesAndAttrs) ->
+ Count = length(NamesAndAttrs),
+ {Data, Len} = encode_names(Vsn, NamesAndAttrs),
+ Size = 1 + 4 + 4 + Len,
+ ToSend = [<<?UINT32(Size), ?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(Count)>>,
+ Data],
+ %%?dbg(true, "xf_send_names: Size=~p size(ToSend)=~p\n",
+ %% [Size, size(list_to_binary(ToSend))]),
+ ssh_connection:send(CM, Channel, ToSend).
+
+xf_send_status(XF, ReqId, ErrorCode) ->
+ xf_send_status(XF, ReqId, ErrorCode, "").
+
+xf_send_status(XF, ReqId, ErrorCode, ErrorMsg) ->
+ xf_send_status(XF, ReqId, ErrorCode, ErrorMsg, <<>>).
+
+xf_send_status(#ssh_xfer{cm = CM, channel = Channel},
+ ReqId, ErrorCode, ErrorMsg, Data) ->
+ LangTag = "en",
+ ELen = length(ErrorMsg),
+ TLen = 2, %% length(LangTag),
+ Size = 1 + 4 + 4 + 4+ELen + 4+TLen + size(Data),
+ ToSend = [<<?UINT32(Size), ?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(ErrorCode)>>,
+ <<?UINT32(ELen)>>, ErrorMsg,
+ <<?UINT32(TLen)>>, LangTag,
+ Data],
+ ssh_connection:send(CM, Channel, ToSend).
+
+xf_send_attr(#ssh_xfer{cm = CM, channel = Channel, vsn = Vsn}, ReqId, Attr) ->
+ EncAttr = encode_ATTR(Vsn, Attr),
+ ALen = size(EncAttr),
+ Size = 1 + 4 + ALen,
+ ToSend = [<<?UINT32(Size), ?SSH_FXP_ATTRS, ?UINT32(ReqId)>>, EncAttr],
+ ssh_connection:send(CM, Channel, ToSend).
+
+xf_send_data(#ssh_xfer{cm = CM, channel = Channel}, ReqId, Data) ->
+ DLen = size(Data),
+ Size = 1 + 4 + 4+DLen,
+ ToSend = [<<?UINT32(Size), ?SSH_FXP_DATA, ?UINT32(ReqId), ?UINT32(DLen)>>,
+ Data],
+ ssh_connection:send(CM, Channel, ToSend).
+
+xf_reply(_XF, << ?SSH_FXP_STATUS, ?UINT32(ReqID), ?UINT32(Status),
+ ?UINT32(ELen), Err:ELen/binary,
+ ?UINT32(LLen), Lang:LLen/binary,
+ Reply/binary >> ) ->
+ Stat = decode_status(Status),
+ {status, ReqID, {Stat,binary_to_list(Err),binary_to_list(Lang),
+ Reply}};
+xf_reply(_XF, << ?SSH_FXP_STATUS, ?UINT32(ReqID), ?UINT32(Status)>> ) ->
+ Stat = decode_status(Status),
+ {status, ReqID, {Stat,"","",<<>>}};
+xf_reply(_XF, <<?SSH_FXP_HANDLE, ?UINT32(ReqID),
+ ?UINT32(HLen), Handle:HLen/binary>>) ->
+ {handle, ReqID, Handle};
+xf_reply(_XF, <<?SSH_FXP_DATA, ?UINT32(ReqID),
+ ?UINT32(DLen), Data:DLen/binary>>) ->
+ {data, ReqID, Data};
+xf_reply(XF, <<?SSH_FXP_NAME, ?UINT32(ReqID),
+ ?UINT32(Count), AData/binary>>) ->
+ %%?dbg(true, "xf_reply ?SSH_FXP_NAME: AData=~p\n", [AData]),
+ {name, ReqID, decode_names(XF#ssh_xfer.vsn, Count, AData)};
+xf_reply(XF, <<?SSH_FXP_ATTRS, ?UINT32(ReqID),
+ AData/binary>>) ->
+ {A, _} = decode_ATTR(XF#ssh_xfer.vsn, AData),
+ {attrs, ReqID, A};
+xf_reply(_XF, <<?SSH_FXP_EXTENDED_REPLY, ?UINT32(ReqID),
+ RData>>) ->
+ {extended_reply, ReqID, RData}.
+
+
+
+decode_status(Status) ->
+ case Status of
+ ?SSH_FX_OK -> ok;
+ ?SSH_FX_EOF -> eof;
+ ?SSH_FX_NO_SUCH_FILE -> no_such_file;
+ ?SSH_FX_PERMISSION_DENIED -> permission_denied;
+ ?SSH_FX_FAILURE -> failure;
+ ?SSH_FX_BAD_MESSAGE -> bad_message;
+ ?SSH_FX_NO_CONNECTION -> no_connection;
+ ?SSH_FX_CONNECTION_LOST -> connection_lost;
+ ?SSH_FX_OP_UNSUPPORTED -> op_unsupported;
+ ?SSH_FX_INVALID_HANDLE -> invalid_handle;
+ ?SSH_FX_NO_SUCH_PATH -> no_such_path;
+ ?SSH_FX_FILE_ALREADY_EXISTS -> file_already_exists;
+ ?SSH_FX_WRITE_PROTECT -> write_protect;
+ ?SSH_FX_NO_MEDIA -> no_media;
+ ?SSH_FX_NO_SPACE_ON_FILESYSTEM -> no_space_on_filesystem;
+ ?SSH_FX_QUOTA_EXCEEDED -> quota_exceeded;
+ ?SSH_FX_UNKNOWN_PRINCIPLE -> unknown_principle;
+ ?SSH_FX_LOCK_CONFlICT -> lock_conflict;
+ ?SSH_FX_NOT_A_DIRECTORY -> not_a_directory;
+ _ -> {error,Status}
+ end.
+
+encode_erlang_status(Status) ->
+ case Status of
+ ok -> ?SSH_FX_OK;
+ eof -> ?SSH_FX_EOF;
+ enoent -> ?SSH_FX_NO_SUCH_FILE;
+ eacces -> ?SSH_FX_PERMISSION_DENIED;
+ _ -> ?SSH_FX_FAILURE
+ end.
+
+decode_ext(<<?UINT32(NameLen), Name:NameLen/binary,
+ ?UINT32(DataLen), Data:DataLen/binary,
+ Tail/binary>>) ->
+ [{binary_to_list(Name), binary_to_list(Data)}
+ | decode_ext(Tail)];
+decode_ext(<<>>) ->
+ [].
+
+%%
+%% Encode rename flags
+%%
+encode_rename_flags(Flags) ->
+ encode_bits(
+ fun(overwrite) -> ?SSH_FXP_RENAME_OVERWRITE;
+ (atomic) -> ?SSH_FXP_RENAME_ATOMIC;
+ (native) -> ?SSH_FXP_RENAME_NATIVE
+ end, Flags).
+
+%% decode_rename_flags(F) ->
+%% decode_bits(F,
+%% [{?SSH_FXP_RENAME_OVERWRITE, overwrite},
+%% {?SSH_FXP_RENAME_ATOMIC, atomic},
+%% {?SSH_FXP_RENAME_NATIVE, native}]).
+
+
+encode_open_flags(Flags) ->
+ encode_bits(
+ fun (read) -> ?SSH_FXF_READ;
+ (write) -> ?SSH_FXF_WRITE;
+ (append) -> ?SSH_FXF_APPEND;
+ (creat) -> ?SSH_FXF_CREAT;
+ (trunc) -> ?SSH_FXF_TRUNC;
+ (excl) -> ?SSH_FXF_EXCL;
+ (create_new) -> ?SSH_FXF_CREATE_NEW;
+ (create_truncate) -> ?SSH_FXF_CREATE_TRUNCATE;
+ (open_existing) -> ?SSH_FXF_OPEN_EXISTING;
+ (open_or_create) -> ?SSH_FXF_OPEN_OR_CREATE;
+ (truncate_existing) -> ?SSH_FXF_TRUNCATE_EXISTING;
+ (append_data) -> ?SSH_FXF_ACCESS_APPEND_DATA;
+ (append_data_atomic) -> ?SSH_FXF_ACCESS_APPEND_DATA_ATOMIC;
+ (text_mode) -> ?SSH_FXF_ACCESS_TEXT_MODE;
+ (read_lock) -> ?SSH_FXF_ACCESS_READ_LOCK;
+ (write_lock) -> ?SSH_FXF_ACCESS_WRITE_LOCK;
+ (delete_lock) -> ?SSH_FXF_ACCESS_DELETE_LOCK
+ end, Flags).
+
+encode_ace_mask(Access) ->
+ encode_bits(
+ fun(read_data) -> ?ACE4_READ_DATA;
+ (list_directory) -> ?ACE4_LIST_DIRECTORY;
+ (write_data) -> ?ACE4_WRITE_DATA;
+ (add_file) -> ?ACE4_ADD_FILE;
+ (append_data) -> ?ACE4_APPEND_DATA;
+ (add_subdirectory) -> ?ACE4_ADD_SUBDIRECTORY;
+ (read_named_attrs) -> ?ACE4_READ_NAMED_ATTRS;
+ (write_named_attrs) -> ?ACE4_WRITE_NAMED_ATTRS;
+ (execute) -> ?ACE4_EXECUTE;
+ (delete_child) -> ?ACE4_DELETE_CHILD;
+ (read_attributes) -> ?ACE4_READ_ATTRIBUTES;
+ (write_attributes) -> ?ACE4_WRITE_ATTRIBUTES;
+ (delete) -> ?ACE4_DELETE;
+ (read_acl) -> ?ACE4_READ_ACL;
+ (write_acl) -> ?ACE4_WRITE_ACL;
+ (write_owner) -> ?ACE4_WRITE_OWNER;
+ (synchronize) -> ?ACE4_SYNCHRONIZE
+ end, Access).
+
+decode_ace_mask(F) ->
+ decode_bits(F,
+ [
+ {?ACE4_READ_DATA, read_data},
+ {?ACE4_LIST_DIRECTORY, list_directory},
+ {?ACE4_WRITE_DATA, write_data},
+ {?ACE4_ADD_FILE, add_file},
+ {?ACE4_APPEND_DATA, append_data},
+ {?ACE4_ADD_SUBDIRECTORY, add_subdirectory},
+ {?ACE4_READ_NAMED_ATTRS, read_named_attrs},
+ {?ACE4_WRITE_NAMED_ATTRS, write_named_attrs},
+ {?ACE4_EXECUTE, execute},
+ {?ACE4_DELETE_CHILD, delete_child},
+ {?ACE4_READ_ATTRIBUTES, read_attributes},
+ {?ACE4_WRITE_ATTRIBUTES, write_attributes},
+ {?ACE4_DELETE, delete},
+ {?ACE4_READ_ACL, read_acl},
+ {?ACE4_WRITE_ACL, write_acl},
+ {?ACE4_WRITE_OWNER, write_owner},
+ {?ACE4_SYNCHRONIZE, synchronize}
+ ]).
+
+decode_open_flags(Vsn, F) when Vsn =< 3 ->
+ decode_bits(F,
+ [
+ {?SSH_FXF_READ, read},
+ {?SSH_FXF_WRITE, write},
+ {?SSH_FXF_APPEND, append},
+ {?SSH_FXF_CREAT, creat},
+ {?SSH_FXF_TRUNC, trunc},
+ {?SSH_FXF_EXCL, excl}
+ ]);
+decode_open_flags(Vsn, F) when Vsn >= 4 ->
+ R = decode_bits(F,
+ [
+ {?SSH_FXF_ACCESS_APPEND_DATA, append_data},
+ {?SSH_FXF_ACCESS_APPEND_DATA_ATOMIC, append_data_atomic},
+ {?SSH_FXF_ACCESS_TEXT_MODE, text_mode},
+ {?SSH_FXF_ACCESS_READ_LOCK, read_lock},
+ {?SSH_FXF_ACCESS_WRITE_LOCK, write_lock},
+ {?SSH_FXF_ACCESS_DELETE_LOCK, delete_lock}
+ ]),
+ AD = case F band ?SSH_FXF_ACCESS_DISPOSITION of
+ ?SSH_FXF_CREATE_NEW -> create_new;
+ ?SSH_FXF_CREATE_TRUNCATE -> create_truncate;
+ ?SSH_FXF_OPEN_EXISTING -> open_existing;
+ ?SSH_FXF_OPEN_OR_CREATE -> open_or_create;
+ ?SSH_FXF_TRUNCATE_EXISTING -> truncate_existing
+ end,
+ [AD | R].
+
+encode_ace_type(Type) ->
+ case Type of
+ access_allowed -> ?ACE4_ACCESS_ALLOWED_ACE_TYPE;
+ access_denied -> ?ACE4_ACCESS_DENIED_ACE_TYPE;
+ system_audit -> ?ACE4_SYSTEM_AUDIT_ACE_TYPE;
+ system_alarm -> ?ACE4_SYSTEM_ALARM_ACE_TYPE
+ end.
+
+decode_ace_type(F) ->
+ case F of
+ ?ACE4_ACCESS_ALLOWED_ACE_TYPE -> access_allowed;
+ ?ACE4_ACCESS_DENIED_ACE_TYPE -> access_denied;
+ ?ACE4_SYSTEM_AUDIT_ACE_TYPE -> system_audit;
+ ?ACE4_SYSTEM_ALARM_ACE_TYPE -> system_alarm
+ end.
+
+encode_ace_flag(Flag) ->
+ encode_bits(
+ fun(file_inherit) -> ?ACE4_FILE_INHERIT_ACE;
+ (directory_inherit) -> ?ACE4_DIRECTORY_INHERIT_ACE;
+ (no_propagte_inherit) -> ?ACE4_NO_PROPAGATE_INHERIT_ACE;
+ (inherit_only) -> ?ACE4_INHERIT_ONLY_ACE;
+ (successful_access) -> ?ACE4_SUCCESSFUL_ACCESS_ACE_FLAG;
+ (failed_access) -> ?ACE4_FAILED_ACCESS_ACE_FLAG;
+ (identifier_group) -> ?ACE4_IDENTIFIER_GROUP
+ end, Flag).
+
+decode_ace_flag(F) ->
+ decode_bits(F,
+ [
+ {?ACE4_FILE_INHERIT_ACE, file_inherit},
+ {?ACE4_DIRECTORY_INHERIT_ACE, directory_inherit},
+ {?ACE4_NO_PROPAGATE_INHERIT_ACE, no_propagte_inherit},
+ {?ACE4_INHERIT_ONLY_ACE, inherit_only},
+ {?ACE4_SUCCESSFUL_ACCESS_ACE_FLAG, successful_access},
+ {?ACE4_FAILED_ACCESS_ACE_FLAG, failed_access},
+ {?ACE4_IDENTIFIER_GROUP, identifier_group}
+ ]).
+
+encode_attr_flags(Vsn, all) ->
+ encode_attr_flags(Vsn,
+ [size, uidgid, permissions,
+ acmodtime, accesstime, createtime,
+ modifytime, acl, ownergroup, subsecond_times,
+ bits, extended]);
+encode_attr_flags(Vsn, Flags) ->
+ encode_bits(
+ fun(size) -> ?SSH_FILEXFER_ATTR_SIZE;
+ (uidgid) when Vsn =<3 -> ?SSH_FILEXFER_ATTR_UIDGID;
+ (permissions) -> ?SSH_FILEXFER_ATTR_PERMISSIONS;
+ (acmodtime) when Vsn =< 3 -> ?SSH_FILEXFER_ATTR_ACMODTIME;
+ (accesstime) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_ACCESSTIME;
+ (createtime) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_CREATETIME;
+ (modifytime) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_MODIFYTIME;
+ (acl) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_ACL;
+ (ownergroup) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_OWNERGROUP;
+ (subsecond_times) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_SUBSECOND_TIMES;
+ (bits) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_BITS;
+ (extended) when Vsn >= 5 -> ?SSH_FILEXFER_ATTR_EXTENDED;
+ (_) -> 0
+ end, Flags).
+
+encode_file_type(Type) ->
+ %%?dbg(true, "encode_file_type(~p)\n", [Type]),
+ case Type of
+ regular -> ?SSH_FILEXFER_TYPE_REGULAR;
+ directory -> ?SSH_FILEXFER_TYPE_DIRECTORY;
+ symlink -> ?SSH_FILEXFER_TYPE_SYMLINK;
+ special -> ?SSH_FILEXFER_TYPE_SPECIAL;
+ unknown -> ?SSH_FILEXFER_TYPE_UNKNOWN;
+ other -> ?SSH_FILEXFER_TYPE_UNKNOWN;
+ socket -> ?SSH_FILEXFER_TYPE_SOCKET;
+ char_device -> ?SSH_FILEXFER_TYPE_CHAR_DEVICE;
+ block_device -> ?SSH_FILEXFER_TYPE_BLOCK_DEVICE;
+ fifo -> ?SSH_FILEXFER_TYPE_FIFO;
+ undefined -> ?SSH_FILEXFER_TYPE_UNKNOWN
+ end.
+
+decode_file_type(Type) ->
+ case Type of
+ ?SSH_FILEXFER_TYPE_REGULAR -> regular;
+ ?SSH_FILEXFER_TYPE_DIRECTORY -> directory;
+ ?SSH_FILEXFER_TYPE_SYMLINK -> symlink;
+ ?SSH_FILEXFER_TYPE_SPECIAL -> special;
+ ?SSH_FILEXFER_TYPE_UNKNOWN -> other; % unknown
+ ?SSH_FILEXFER_TYPE_SOCKET -> socket;
+ ?SSH_FILEXFER_TYPE_CHAR_DEVICE -> char_device;
+ ?SSH_FILEXFER_TYPE_BLOCK_DEVICE -> block_device;
+ ?SSH_FILEXFER_TYPE_FIFO -> fifo
+ end.
+
+encode_attrib_bits(Bits) ->
+ encode_bits(
+ fun(readonly) -> ?SSH_FILEXFER_ATTR_FLAGS_READONLY;
+ (system) -> ?SSH_FILEXFER_ATTR_FLAGS_SYSTEM;
+ (hidden) -> ?SSH_FILEXFER_ATTR_FLAGS_HIDDEN;
+ (case_insensitive) -> ?SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE;
+ (arcive) -> ?SSH_FILEXFER_ATTR_FLAGS_ARCHIVE;
+ (encrypted) -> ?SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED;
+ (compressed) -> ?SSH_FILEXFER_ATTR_FLAGS_COMPRESSED;
+ (sparse) -> ?SSH_FILEXFER_ATTR_FLAGS_SPARSE;
+ (append_only) -> ?SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY;
+ (immutable) -> ?SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE;
+ (sync) -> ?SSH_FILEXFER_ATTR_FLAGS_SYNC
+ end, Bits).
+
+decode_attrib_bits(F) ->
+ decode_bits(F,
+ [{?SSH_FILEXFER_ATTR_FLAGS_READONLY, readonly},
+ {?SSH_FILEXFER_ATTR_FLAGS_SYSTEM, system},
+ {?SSH_FILEXFER_ATTR_FLAGS_HIDDEN, hidden},
+ {?SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE, case_insensitive},
+ {?SSH_FILEXFER_ATTR_FLAGS_ARCHIVE, arcive},
+ {?SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED, encrypted},
+ {?SSH_FILEXFER_ATTR_FLAGS_COMPRESSED, compressed},
+ {?SSH_FILEXFER_ATTR_FLAGS_SPARSE, sparse},
+ {?SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY, append_only},
+ {?SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE, immutable},
+ {?SSH_FILEXFER_ATTR_FLAGS_SYNC, sync}]).
+
+
+%%
+%% Encode file attributes
+%%
+encode_ATTR(Vsn, A) ->
+ {Flags,As} =
+ encode_As(Vsn,
+ [{size, A#ssh_xfer_attr.size},
+ {ownergroup, A#ssh_xfer_attr.owner},
+ {ownergroup, A#ssh_xfer_attr.group},
+ {permissions, A#ssh_xfer_attr.permissions},
+ {acmodtime, A#ssh_xfer_attr.atime},
+ {acmodtime, A#ssh_xfer_attr.mtime},
+ {accesstime, A#ssh_xfer_attr.atime},
+ {subsecond_times, A#ssh_xfer_attr.atime_nseconds},
+ {createtime, A#ssh_xfer_attr.createtime},
+ {subsecond_times, A#ssh_xfer_attr.createtime_nseconds},
+ {modifytime, A#ssh_xfer_attr.mtime},
+ {subsecond_times, A#ssh_xfer_attr.mtime_nseconds},
+ {acl, A#ssh_xfer_attr.acl},
+ {bits, A#ssh_xfer_attr.attrib_bits},
+ {extended, A#ssh_xfer_attr.extensions}],
+ 0, []),
+ Type = encode_file_type(A#ssh_xfer_attr.type),
+ %%?dbg(true, "encode_ATTR: Vsn=~p A=~p As=~p Flags=~p Type=~p",
+ %% [Vsn, A, As, Flags, Type]),
+ Result = list_to_binary([?uint32(Flags),
+ if Vsn >= 5 ->
+ ?byte(Type);
+ true ->
+ (<<>>)
+ end, As]),
+ %% ?dbg(true, " Result=~p\n", [Result]),
+ Result.
+
+
+encode_As(Vsn, [{_AName, undefined}|As], Flags, Acc) ->
+ encode_As(Vsn, As, Flags, Acc);
+encode_As(Vsn, [{AName, X}|As], Flags, Acc) ->
+ case AName of
+ size ->
+ encode_As(Vsn, As,Flags bor ?SSH_FILEXFER_ATTR_SIZE,
+ [?uint64(X) | Acc]);
+ ownergroup when Vsn=<4 ->
+ encode_As(Vsn, As,Flags bor ?SSH_FILEXFER_ATTR_UIDGID,
+ [?uint32(X) | Acc]);
+ ownergroup when Vsn>=5 ->
+ X1 = list_to_binary(integer_to_list(X)), % TODO: check owner and group
+ encode_As(Vsn, As,Flags bor ?SSH_FILEXFER_ATTR_OWNERGROUP,
+ [?binary(X1) | Acc]);
+ permissions ->
+ encode_As(Vsn, As,Flags bor ?SSH_FILEXFER_ATTR_PERMISSIONS,
+ [?uint32(X) | Acc]);
+ acmodtime when Vsn=<3 ->
+ encode_As(Vsn, As,Flags bor ?SSH_FILEXFER_ATTR_ACMODTIME,
+ [?uint32(X) | Acc]);
+ accesstime when Vsn>=5 ->
+ encode_As(Vsn, As, Flags bor ?SSH_FILEXFER_ATTR_ACCESSTIME,
+ [?uint64(X) | Acc]);
+ createtime when Vsn>=5->
+ encode_As(Vsn, As, Flags bor ?SSH_FILEXFER_ATTR_CREATETIME,
+ [?uint64(X) | Acc]);
+ modifytime when Vsn>=5 ->
+ encode_As(Vsn, As, Flags bor ?SSH_FILEXFER_ATTR_MODIFYTIME,
+ [?uint64(X) | Acc]);
+ subsecond_times when Vsn>=5 ->
+ encode_As(Vsn, As, Flags bor ?SSH_FILEXFER_ATTR_SUBSECOND_TIMES,
+ [?uint64(X) | Acc]);
+ acl when Vsn >=5 ->
+ encode_As(Vsn, As, Flags bor ?SSH_FILEXFER_ATTR_ACL,
+ [encode_acl(X) | Acc]);
+ bits when Vsn>=5 ->
+ F = encode_attrib_bits(X),
+ encode_As(Vsn, As, Flags bor ?SSH_FILEXFER_ATTR_BITS,
+ [?uint32(F) | Acc]);
+ extended ->
+ encode_As(Vsn, As, Flags bor ?SSH_FILEXFER_ATTR_EXTENDED,
+ [encode_extensions(X) | Acc]);
+ _ ->
+ encode_As(Vsn, As, Flags, Acc)
+ end;
+encode_As(_Vsn, [], Flags, Acc) ->
+ {Flags, reverse(Acc)}.
+
+
+decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
+ %%?dbg(true, "decode_ATTR: Vsn=~p Flags=~p Tail=~p\n", [Vsn, Flags, Tail]),
+ {Type,Tail2} =
+ if Vsn =< 3 ->
+ {?SSH_FILEXFER_TYPE_UNKNOWN, Tail};
+ Vsn >= 5 ->
+ <<?BYTE(T), TL/binary>> = Tail,
+ {T, TL}
+ end,
+ decode_As(Vsn,
+ [{size, #ssh_xfer_attr.size},
+ {ownergroup, #ssh_xfer_attr.owner},
+ {ownergroup, #ssh_xfer_attr.group},
+ {permissions, #ssh_xfer_attr.permissions},
+ {acmodtime, #ssh_xfer_attr.atime},
+ {acmodtime, #ssh_xfer_attr.mtime},
+ {accesstime, #ssh_xfer_attr.atime},
+ {subsecond_times, #ssh_xfer_attr.atime_nseconds},
+ {createtime, #ssh_xfer_attr.createtime},
+ {subsecond_times, #ssh_xfer_attr.createtime_nseconds},
+ {modifytime, #ssh_xfer_attr.mtime},
+ {subsecond_times, #ssh_xfer_attr.mtime_nseconds},
+ {acl, #ssh_xfer_attr.acl},
+ {bits, #ssh_xfer_attr.attrib_bits},
+ {extended, #ssh_xfer_attr.extensions}],
+ #ssh_xfer_attr { type = decode_file_type(Type) },
+ Flags,
+ Tail2).
+
+decode_As(Vsn, [{AName, AField}|As], R, Flags, Tail) ->
+ %%?dbg(false, "decode_As: Vsn=~p AName=~p AField=~p Flags=~p Tail=~p\n", [Vsn, AName, AField, Flags, Tail]),
+ case AName of
+ size when ?is_set(?SSH_FILEXFER_ATTR_SIZE, Flags) ->
+ <<?UINT64(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ ownergroup when ?is_set(?SSH_FILEXFER_ATTR_UIDGID, Flags),Vsn=<3 ->
+ <<?UINT32(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ ownergroup when ?is_set(?SSH_FILEXFER_ATTR_OWNERGROUP, Flags),Vsn>=5 ->
+ <<?UINT32(Len), Bin:Len/binary, Tail2/binary>> = Tail,
+ X = binary_to_list(Bin),
+ %%?dbg(true, "ownergroup X=~p\n", [X]),
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+
+ permissions when ?is_set(?SSH_FILEXFER_ATTR_PERMISSIONS,Flags),Vsn>=5->
+ <<?UINT32(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+
+ permissions when ?is_set(?SSH_FILEXFER_ATTR_PERMISSIONS,Flags),Vsn=<3->
+ <<?UINT32(X), Tail2/binary>> = Tail,
+ R1 = setelement(AField, R, X),
+ Type = case X band ?S_IFMT of
+ ?S_IFDIR -> directory;
+ ?S_IFCHR -> char_device;
+ ?S_IFBLK -> block_device;
+ ?S_IFIFO -> fifi;
+ ?S_IFREG -> regular;
+ ?S_IFSOCK -> socket;
+ ?S_IFLNK -> symlink;
+ _ -> unknown
+ end,
+ decode_As(Vsn, As, R1#ssh_xfer_attr { type=Type}, Flags, Tail2);
+
+ acmodtime when ?is_set(?SSH_FILEXFER_ATTR_ACMODTIME,Flags),Vsn=<3 ->
+ <<?UINT32(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ accesstime when ?is_set(?SSH_FILEXFER_ATTR_ACCESSTIME,Flags),Vsn>=5 ->
+ <<?UINT64(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ modifytime when ?is_set(?SSH_FILEXFER_ATTR_MODIFYTIME,Flags),Vsn>=5 ->
+ <<?UINT64(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ createtime when ?is_set(?SSH_FILEXFER_ATTR_CREATETIME,Flags),Vsn>=5 ->
+ <<?UINT64(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ subsecond_times when ?is_set(?SSH_FILEXFER_ATTR_SUBSECOND_TIMES,Flags),Vsn>=5 ->
+ <<?UINT32(X), Tail2/binary>> = Tail,
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ acl when ?is_set(?SSH_FILEXFER_ATTR_ACL, Flags), Vsn>=5 ->
+ {X,Tail2} = decode_acl(Tail),
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ bits when ?is_set(?SSH_FILEXFER_ATTR_BITS, Flags), Vsn >=5 ->
+ <<?UINT32(Y), Tail2/binary>> = Tail,
+ X = decode_attrib_bits(Y),
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ extended when ?is_set(?SSH_FILEXFER_ATTR_EXTENDED, Flags) ->
+ {X,Tail2} = decode_extended(Tail),
+ decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
+ _ ->
+ decode_As(Vsn, As, R, Flags, Tail)
+ end;
+decode_As(_Vsn, [], R, _, Tail) ->
+ {R, Tail}.
+
+
+
+
+decode_names(_Vsn, 0, _Data) ->
+ [];
+decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
+ ?UINT32(LLen), _LongName:LLen/binary,
+ Tail/binary>>) when Vsn =< 3 ->
+ Name = binary_to_list(FileName),
+ %%?dbg(true, "decode_names: ~p\n", [Name]),
+ {A, Tail2} = decode_ATTR(Vsn, Tail),
+ [{Name, A} | decode_names(Vsn, I-1, Tail2)];
+decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
+ Tail/binary>>) when Vsn >= 4 ->
+ Name = binary_to_list(FileName),
+ %%?dbg(true, "decode_names: ~p\n", [Name]),
+ {A, Tail2} = decode_ATTR(Vsn, Tail),
+ [{Name, A} | decode_names(Vsn, I-1, Tail2)].
+
+encode_names(Vsn, NamesAndAttrs) ->
+ lists:mapfoldl(fun(N, L) -> encode_name(Vsn, N, L) end, 0, NamesAndAttrs).
+
+encode_name(Vsn, {Name,Attr}, Len) when Vsn =< 3 ->
+ NLen = length(Name),
+ %%?dbg(true, "encode_name: Vsn=~p Name=~p Attr=~p\n",
+ %% [Vsn, Name, Attr]),
+ EncAttr = encode_ATTR(Vsn, Attr),
+ ALen = size(EncAttr),
+ NewLen = Len + NLen*2 + 4 + 4 + ALen,
+ {[<<?UINT32(NLen)>>, Name, <<?UINT32(NLen)>>, Name, EncAttr], NewLen};
+encode_name(Vsn, {Name,Attr}, Len) when Vsn >= 4 ->
+ NLen = length(Name),
+ EncAttr = encode_ATTR(Vsn, Attr),
+ ALen = size(EncAttr),
+ {[<<?UINT32(NLen)>>, Name, EncAttr],
+ Len + 4 + NLen + ALen}.
+
+encode_acl(ACLList) ->
+ Count = length(ACLList),
+ [?uint32(Count) | encode_acl_items(ACLList)].
+
+encode_acl_items([ACE|As]) ->
+ Type = encode_ace_type(ACE#ssh_xfer_ace.type),
+ Flag = encode_ace_flag(ACE#ssh_xfer_ace.flag),
+ Mask = encode_ace_mask(ACE#ssh_xfer_ace.mask),
+ Who = list_to_binary(ACE#ssh_xfer_ace.who),
+ [?uint32(Type), ?uint32(Flag), ?uint32(Mask),
+ ?binary(Who) | encode_acl_items(As)];
+encode_acl_items([]) ->
+ [].
+
+
+decode_acl(<<?UINT32(Count), Tail/binary>>) ->
+ decode_acl_items(Count, Tail, []).
+
+decode_acl_items(0, Tail, Acc) ->
+ {reverse(Acc), Tail};
+decode_acl_items(I, <<?UINT32(Type),
+ ?UINT32(Flag),
+ ?UINT32(Mask),
+ ?UINT32(WLen), BWho:WLen/binary,
+ Tail/binary>>, Acc) ->
+ decode_acl_items(I-1, Tail,
+ [#ssh_xfer_ace { type = decode_ace_type(Type),
+ flag = decode_ace_flag(Flag),
+ mask = decode_ace_mask(Mask),
+ who = binary_to_list(BWho)} | Acc]).
+
+encode_extensions(Exts) ->
+ Count = length(Exts),
+ [?uint32(Count) | encode_ext(Exts)].
+
+encode_ext([{Type, Data} | Exts]) ->
+ [?string(Type), ?string(Data) | encode_ext(Exts)];
+encode_ext([]) ->
+ [].
+
+
+decode_extended(<<?UINT32(Count), Tail/binary>>) ->
+ decode_ext(Count, Tail, []).
+
+decode_ext(0, Tail, Acc) ->
+ {reverse(Acc), Tail};
+decode_ext(I, <<?UINT32(TLen), Type:TLen/binary,
+ ?UINT32(DLen), Data:DLen/binary,
+ Tail/binary>>, Acc) ->
+ decode_ext(I-1, Tail, [{binary_to_list(Type), Data}|Acc]).
+
+
+
+%% Encode bit encoded flags
+encode_bits(Fun, BitNames) ->
+ encode_bits(Fun, 0, BitNames).
+
+encode_bits(Fun, F, [Bit|BitNames]) ->
+ encode_bits(Fun, Fun(Bit) bor F, BitNames);
+encode_bits(_Fun, F, []) ->
+ F.
+
+%% Decode bit encoded flags
+decode_bits(F, [{Bit,BitName}|Bits]) ->
+ if F band Bit == Bit ->
+ [BitName | decode_bits(F, Bits)];
+ true ->
+ decode_bits(F, Bits)
+ end;
+decode_bits(_F, []) ->
+ [].
diff --git a/lib/ssh/src/ssh_xfer.hrl b/lib/ssh/src/ssh_xfer.hrl
new file mode 100755
index 0000000000..f32ec5f774
--- /dev/null
+++ b/lib/ssh/src/ssh_xfer.hrl
@@ -0,0 +1,251 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+%%% Description: SFTP defines
+-define(SSH_SFTP_PROTOCOL_VERSION, 6).
+%%%----------------------------------------------------------------------
+%%% # SSH_FXP_xxx
+%%% Description: Request and initialization packet types for file transfer
+%%% protocol.
+%%%----------------------------------------------------------------------
+-define(SSH_FXP_INIT, 1).
+-define(SSH_FXP_VERSION, 2).
+-define(SSH_FXP_OPEN, 3).
+-define(SSH_FXP_CLOSE, 4).
+-define(SSH_FXP_READ, 5).
+-define(SSH_FXP_WRITE, 6).
+-define(SSH_FXP_LSTAT, 7).
+-define(SSH_FXP_FSTAT, 8).
+-define(SSH_FXP_SETSTAT, 9).
+-define(SSH_FXP_FSETSTAT, 10).
+-define(SSH_FXP_OPENDIR, 11).
+-define(SSH_FXP_READDIR, 12).
+-define(SSH_FXP_REMOVE, 13).
+-define(SSH_FXP_MKDIR, 14).
+-define(SSH_FXP_RMDIR, 15).
+-define(SSH_FXP_REALPATH, 16).
+-define(SSH_FXP_STAT, 17).
+-define(SSH_FXP_RENAME, 18).
+-define(SSH_FXP_READLINK, 19).
+-define(SSH_FXP_SYMLINK, 20).
+-define(SSH_FXP_STATUS, 101).
+-define(SSH_FXP_HANDLE, 102).
+-define(SSH_FXP_DATA, 103).
+-define(SSH_FXP_NAME, 104).
+-define(SSH_FXP_ATTRS, 105).
+-define(SSH_FXP_EXTENDED, 200).
+-define(SSH_FXP_EXTENDED_REPLY, 201).
+
+%%%----------------------------------------------------------------------
+%%% # SSH_FX_xxx
+%%% Description: Response packet types for file transfer protocol.
+%%%----------------------------------------------------------------------
+
+-define(SSH_FX_OK, 0).
+-define(SSH_FX_EOF, 1).
+-define(SSH_FX_NO_SUCH_FILE, 2).
+-define(SSH_FX_PERMISSION_DENIED, 3).
+-define(SSH_FX_FAILURE, 4).
+-define(SSH_FX_BAD_MESSAGE, 5).
+-define(SSH_FX_NO_CONNECTION, 6).
+-define(SSH_FX_CONNECTION_LOST, 7).
+-define(SSH_FX_OP_UNSUPPORTED, 8).
+-define(SSH_FX_INVALID_HANDLE, 9).
+-define(SSH_FX_NO_SUCH_PATH, 10).
+-define(SSH_FX_FILE_ALREADY_EXISTS, 11).
+-define(SSH_FX_WRITE_PROTECT, 12).
+-define(SSH_FX_NO_MEDIA, 13).
+-define(SSH_FX_NO_SPACE_ON_FILESYSTEM, 14).
+-define(SSH_FX_QUOTA_EXCEEDED, 15).
+-define(SSH_FX_UNKNOWN_PRINCIPLE, 16).
+-define(SSH_FX_LOCK_CONFlICT, 17).
+-define(SSH_FX_DIR_NOT_EMPTY, 18).
+-define(SSH_FX_NOT_A_DIRECTORY, 19).
+-define(SSH_FX_FILE_IS_A_DIRECTORY, 24).
+
+%%%----------------------------------------------------------------------
+%%% # SSH_FILEXFER_xxx
+%%% Description: Bits for file attributes bit mask
+%%%----------------------------------------------------------------------
+-define(SSH_FILEXFER_ATTR_SIZE, 16#00000001). %% vsn 3,5
+-define(SSH_FILEXFER_ATTR_UIDGID, 16#00000002). %% vsn 3
+-define(SSH_FILEXFER_ATTR_PERMISSIONS, 16#00000004). %% vsn 3,5
+-define(SSH_FILEXFER_ATTR_ACCESSTIME, 16#00000008). %% vsn 5
+-define(SSH_FILEXFER_ATTR_ACMODTIME, 16#00000008). %% vsn 3
+-define(SSH_FILEXFER_ATTR_CREATETIME, 16#00000010). %% vsn 5
+-define(SSH_FILEXFER_ATTR_MODIFYTIME, 16#00000020) .%% vsn 5
+-define(SSH_FILEXFER_ATTR_ACL, 16#00000040). %% vsn 5
+-define(SSH_FILEXFER_ATTR_OWNERGROUP, 16#00000080). %% vsn 5
+-define(SSH_FILEXFER_ATTR_SUBSECOND_TIMES, 16#00000100). %% vsn 5
+-define(SSH_FILEXFER_ATTR_BITS, 16#00000200). %% vsn 5
+-define(SSH_FILEXFER_ATTR_EXTENDED, 16#80000000). %% vsn 3,5
+
+%% File types
+-define(SSH_FILEXFER_TYPE_REGULAR, 1).
+-define(SSH_FILEXFER_TYPE_DIRECTORY, 2).
+-define(SSH_FILEXFER_TYPE_SYMLINK, 3).
+-define(SSH_FILEXFER_TYPE_SPECIAL, 4).
+-define(SSH_FILEXFER_TYPE_UNKNOWN, 5).
+-define(SSH_FILEXFER_TYPE_SOCKET, 6).
+-define(SSH_FILEXFER_TYPE_CHAR_DEVICE, 7).
+-define(SSH_FILEXFER_TYPE_BLOCK_DEVICE, 8).
+-define(SSH_FILEXFER_TYPE_FIFO, 9).
+
+%% Permissions
+-define(S_IRUSR, 8#0000400).
+-define(S_IWUSR, 8#0000200).
+-define(S_IXUSR, 8#0000100).
+-define(S_IRGRP, 8#0000040).
+-define(S_IWGRP, 8#0000020).
+-define(S_IXGRP, 8#0000010).
+-define(S_IROTH, 8#0000004).
+-define(S_IWOTH, 8#0000002).
+-define(S_IXOTH, 8#0000001).
+-define(S_ISUID, 8#0004000).
+-define(S_ISGID, 8#0002000).
+-define(S_ISVTX, 8#0001000).
+%% type bits (version 3 only?)
+-define(S_IFMT, 8#0170000). %% file type mask
+-define(S_IFDIR, 8#0040000).
+-define(S_IFCHR, 8#0020000).
+-define(S_IFBLK, 8#0060000).
+-define(S_IFIFO, 8#0010000).
+-define(S_IFREG, 8#0100000).
+-define(S_IFLNK, 8#0120000).
+-define(S_IFSOCK, 8#0140000).
+
+%% ACE-Type
+-define(ACE4_ACCESS_ALLOWED_ACE_TYPE, 16#00000000).
+-define(ACE4_ACCESS_DENIED_ACE_TYPE, 16#00000001).
+-define(ACE4_SYSTEM_AUDIT_ACE_TYPE, 16#00000002).
+-define(ACE4_SYSTEM_ALARM_ACE_TYPE, 16#00000003).
+
+%% ACE-Flag
+-define(ACE4_FILE_INHERIT_ACE, 16#00000001).
+-define(ACE4_DIRECTORY_INHERIT_ACE, 16#00000002).
+-define(ACE4_NO_PROPAGATE_INHERIT_ACE, 16#00000004).
+-define(ACE4_INHERIT_ONLY_ACE, 16#00000008).
+-define(ACE4_SUCCESSFUL_ACCESS_ACE_FLAG, 16#00000010).
+-define(ACE4_FAILED_ACCESS_ACE_FLAG, 16#00000020).
+-define(ACE4_IDENTIFIER_GROUP, 16#00000040).
+
+%% ACE-Mask
+-define(ACE4_READ_DATA, 16#00000001).
+-define(ACE4_LIST_DIRECTORY, 16#00000001).
+-define(ACE4_WRITE_DATA, 16#00000002).
+-define(ACE4_ADD_FILE, 16#00000002).
+-define(ACE4_APPEND_DATA, 16#00000004).
+-define(ACE4_ADD_SUBDIRECTORY, 16#00000004).
+-define(ACE4_READ_NAMED_ATTRS, 16#00000008).
+-define(ACE4_WRITE_NAMED_ATTRS, 16#00000010).
+-define(ACE4_EXECUTE, 16#00000020).
+-define(ACE4_DELETE_CHILD, 16#00000040).
+-define(ACE4_READ_ATTRIBUTES, 16#00000080).
+-define(ACE4_WRITE_ATTRIBUTES, 16#00000100).
+-define(ACE4_DELETE, 16#00010000).
+-define(ACE4_READ_ACL, 16#00020000).
+-define(ACE4_WRITE_ACL, 16#00040000).
+-define(ACE4_WRITE_OWNER, 16#00080000).
+-define(ACE4_SYNCHRONIZE, 16#00100000).
+
+%% Attrib-bits
+-define(SSH_FILEXFER_ATTR_FLAGS_READONLY, 16#00000001).
+-define(SSH_FILEXFER_ATTR_FLAGS_SYSTEM, 16#00000002).
+-define(SSH_FILEXFER_ATTR_FLAGS_HIDDEN, 16#00000004).
+-define(SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE, 16#00000008).
+-define(SSH_FILEXFER_ATTR_FLAGS_ARCHIVE, 16#00000010).
+-define(SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED, 16#00000020).
+-define(SSH_FILEXFER_ATTR_FLAGS_COMPRESSED, 16#00000040).
+-define(SSH_FILEXFER_ATTR_FLAGS_SPARSE, 16#00000080).
+-define(SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY, 16#00000100).
+-define(SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE, 16#00000200).
+-define(SSH_FILEXFER_ATTR_FLAGS_SYNC, 16#00000400).
+
+%% Open flags (version 3)
+-define(SSH_FXF_READ, 16#00000001).
+-define(SSH_FXF_WRITE, 16#00000002).
+-define(SSH_FXF_APPEND, 16#00000004).
+-define(SSH_FXF_CREAT, 16#00000008).
+-define(SSH_FXF_TRUNC, 16#00000010).
+-define(SSH_FXF_EXCL, 16#00000020).
+
+%% Open flags (version 5)
+-define(SSH_FXF_ACCESS_DISPOSITION, 16#00000007).
+-define(SSH_FXF_CREATE_NEW, 16#00000000).
+-define(SSH_FXF_CREATE_TRUNCATE, 16#00000001).
+-define(SSH_FXF_OPEN_EXISTING, 16#00000002).
+-define(SSH_FXF_OPEN_OR_CREATE, 16#00000003).
+-define(SSH_FXF_TRUNCATE_EXISTING, 16#00000004).
+-define(SSH_FXF_ACCESS_APPEND_DATA, 16#00000008).
+-define(SSH_FXF_ACCESS_APPEND_DATA_ATOMIC, 16#00000010).
+-define(SSH_FXF_ACCESS_TEXT_MODE, 16#00000020).
+-define(SSH_FXF_ACCESS_READ_LOCK, 16#00000040).
+-define(SSH_FXF_ACCESS_WRITE_LOCK, 16#00000080).
+-define(SSH_FXF_ACCESS_DELETE_LOCK, 16#00000100).
+
+%% Rename flags
+-define(SSH_FXP_RENAME_OVERWRITE, 16#00000001).
+-define(SSH_FXP_RENAME_ATOMIC, 16#00000002).
+-define(SSH_FXP_RENAME_NATIVE, 16#00000004).
+
+
+-define(SSH_FILEXFER_LARGEFILESIZE, (1 bsl 63)).
+
+-record(ssh_xfer_attr,
+ {
+ type, %% regular, dirctory, symlink, ...
+ size,
+ owner,
+ group,
+ permissions,
+ atime,
+ atime_nseconds,
+ createtime,
+ createtime_nseconds,
+ mtime,
+ mtime_nseconds,
+ acl,
+ attrib_bits,
+ extensions %% list of [{type,data}]
+ }).
+
+-record(ssh_xfer_ace,
+ {
+ type,
+ flag,
+ mask,
+ who
+ }).
+
+%% connection endpoint and server/client info
+-record(ssh_xfer,
+ {
+ vsn, %% server version
+ ext, %% server extensions
+ cm, %% connection mgr
+ channel %% SFTP channel
+ }).
+
+
+
+
+
+
diff --git a/lib/ssh/src/sshc_sup.erl b/lib/ssh/src/sshc_sup.erl
new file mode 100644
index 0000000000..265d1a1cd6
--- /dev/null
+++ b/lib/ssh/src/sshc_sup.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The ssh client subsystem supervisor
+%%----------------------------------------------------------------------
+
+-module(sshc_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, start_child/1]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(Args) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, [Args]).
+
+start_child(Args) ->
+ supervisor:start_child(?MODULE, Args).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init(Args) ->
+ RestartStrategy = simple_one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ {ok, {{RestartStrategy, MaxR, MaxT}, [child_spec(Args)]}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+child_spec(_) ->
+ Name = undefined, % As simple_one_for_one is used.
+ StartFunc = {ssh_connection_controler, start_link, []},
+ Restart = temporary,
+% Shutdown = infinity,
+ Shutdown = 5000,
+ Modules = [ssh_connection_controler],
+% Type = supervisor,
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
diff --git a/lib/ssh/src/sshd_sup.erl b/lib/ssh/src/sshd_sup.erl
new file mode 100644
index 0000000000..9c9ba5958c
--- /dev/null
+++ b/lib/ssh/src/sshd_sup.erl
@@ -0,0 +1,111 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The top supervisor for ssh servers hangs under
+%% ssh_sup.
+%%----------------------------------------------------------------------
+
+-module(sshd_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, start_child/1, stop_child/1,
+ stop_child/2, system_name/1]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(Servers) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, [Servers]).
+
+start_child(ServerOpts) ->
+ Address = proplists:get_value(address, ServerOpts),
+ Port = proplists:get_value(port, ServerOpts),
+ case ssh_system_sup:system_supervisor(Address, Port) of
+ undefined ->
+ Spec = child_spec(Address, Port, ServerOpts),
+ case supervisor:start_child(?MODULE, Spec) of
+ {error, already_present} ->
+ Name = id(Address, Port),
+ supervisor:delete_child(?MODULE, Name),
+ supervisor:start_child(?MODULE, Spec);
+ Reply ->
+ Reply
+ end;
+ Pid ->
+ AccPid = ssh_system_sup:acceptor_supervisor(Pid),
+ ssh_acceptor_sup:start_child(AccPid, ServerOpts)
+ end.
+
+stop_child(Name) ->
+ case supervisor:terminate_child(?MODULE, Name) of
+ ok ->
+ supervisor:delete_child(?MODULE, Name);
+ Error ->
+ Error
+ end.
+
+stop_child(Address, Port) ->
+ Name = id(Address, Port),
+ stop_child(Name).
+
+system_name(SysSup) ->
+ Children = supervisor:which_children(sshd_sup),
+ system_name(SysSup, Children).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([Servers]) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Fun = fun(ServerOpts) ->
+ Address = proplists:get_value(address, ServerOpts),
+ Port = proplists:get_value(port, ServerOpts),
+ child_spec(Address, Port, ServerOpts)
+ end,
+ Children = lists:map(Fun, Servers),
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+child_spec(Address, Port, ServerOpts) ->
+ Name = id(Address, Port),
+ StartFunc = {ssh_system_sup, start_link, [ServerOpts]},
+ Restart = transient,
+ Shutdown = infinity,
+ Modules = [ssh_system_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+id(Address, Port) ->
+ {server, ssh_system_sup, Address, Port}.
+
+system_name([], _ ) ->
+ undefined;
+system_name(SysSup, [{Name, SysSup, _, _} | _]) ->
+ Name;
+system_name(SysSup, [_ | Rest]) ->
+ system_name(SysSup, Rest).
diff --git a/lib/ssh/subdirs.mk b/lib/ssh/subdirs.mk
new file mode 100644
index 0000000000..71ab06952f
--- /dev/null
+++ b/lib/ssh/subdirs.mk
@@ -0,0 +1,4 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+SUB_DIRS = src c_src
+
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
new file mode 100644
index 0000000000..016fb30c69
--- /dev/null
+++ b/lib/ssh/vsn.mk
@@ -0,0 +1,73 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+SSH_VSN = 1.1.7
+APP_VSN = "ssh-$(SSH_VSN)"
+
+TICKETS = OTP-8121 \
+ OTP-8277 \
+ OTP-8278 \
+ OTP-8201
+
+TICKETS_1.1.6 = OTP-8110 \
+ OTP-8162 \
+ OTP-8173 \
+ OTP-8174 \
+ OTP-8175 \
+ OTP-8176
+
+TICKETS_1.1.5 = OTP-8159 \
+ OTP-8160 \
+ OTP-8161
+
+TICKETS_1.1.4 = OTP-8071
+
+TICKETS_1.1.3 = OTP-7996 \
+ OTP-8034 \
+ OTP-8035
+
+TICKETS_1.1.2 = OTP-7914 \
+ OTP-7917 \
+ OTP-7918 \
+ OTP-7921 \
+ OTP-7919 \
+ OTP-7930 \
+ OTP-7957
+
+TICKETS_1.1.1 = OTP-7828 \
+ OTP-7795 \
+ OTP-7807 \
+ OTP-7808 \
+ OTP-7809
+
+TICKETS_1.1 = OTP-7676 \
+ OTP-7683 \
+ OTP-7685 \
+ OTP-7766 \
+ OTP-7767 \
+ OTP-7768 \
+ OTP-7770 \
+ OTP-7456 \
+ OTP-7769 \
+ OTP-7516 \
+ OTP-7645 \
+
+TICKETS_1.0.2 = \
+ OTP-7141\
+
+TICKETS_1.0.1 = \
+ OTP-7318 \
+ OTP-7305 \
+ OTP-7564 \
+ OTP-7565 \
+ OTP-7566 \
+
+TICKETS_1.0 = \
+ OTP-7485 \
+ OTP-7504 \
+ OTP-7356 \
+ OTP-7502 \
+ OTP-7503
+
+TICKETS_0.9.9.6 = \
+ OTP-7246 \
+ OTP-7247 \ \ No newline at end of file