From 2084f7e079c951fdadebe23dcff5ec247c6e0158 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 10 Oct 2012 15:27:10 +0200 Subject: ssh: Add Users Guide and enhance man pages --- lib/ssh/doc/src/using_ssh.xml | 288 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 lib/ssh/doc/src/using_ssh.xml (limited to 'lib/ssh/doc/src/using_ssh.xml') diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml new file mode 100644 index 0000000000..db17c6fd1c --- /dev/null +++ b/lib/ssh/doc/src/using_ssh.xml @@ -0,0 +1,288 @@ + + + + +
+ + 2012 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Getting started + using_ssh.xml +
+ +
+ General information +

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

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

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

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

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

+ +

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

+
+ +

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

+ +

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

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

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

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

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

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

There is two ways of shuting down an SSH daemon

+ +

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

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

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

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

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

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

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

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

Run the openssh sftp client

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

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

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

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

+ + + 1> ssh:start(). + ok + 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon/ssh_host_rsa_key"}, + {user_dir, "/tmp/otptest_user/.ssh"} + {subsystems, [{"echo_n", {ssh_echo_server, [10]}}]}]). + {ok,<0.54.0>} + 3> + + + + 1> ssh:start(). + ok + 2>{ok, ConnectionRef} = ssh:connect("tarlop", 8989, [{user_dir, "/tmp/otptest_user/.ssh"}]). + {ok,<0.57.0>} + 3>{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity). + 4> success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity). + 5> ok = ssh_connection:send(ConnectionRef, ChannelId, "0123456789", infinity), + 6> flush(). + {ssh_msg, <0.57.0>, {data, 0, 1, "0123456789"}} + {ssh_msg, <0.57.0>, {eof, 0}} + {ssh_msg, <0.57.0>, {closed, 0}} + 7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity), + + +
+ +
-- cgit v1.2.3