aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/forwarding.dox63
-rw-r--r--doc/guided_tour.dox38
-rw-r--r--doc/introduction.dox2
-rw-r--r--doc/scp.dox252
-rw-r--r--doc/sftp.dox2
-rw-r--r--doc/tbd.dox31
6 files changed, 349 insertions, 39 deletions
diff --git a/doc/forwarding.dox b/doc/forwarding.dox
new file mode 100644
index 00000000..f6a2869e
--- /dev/null
+++ b/doc/forwarding.dox
@@ -0,0 +1,63 @@
+/**
+@page forwarding Chapter 7: Forwarding connections
+@section forwarding_connections Forwarding connections
+
+Port forwarding comes in SSH protocol in two different flavours:
+direct or reverse port forwarding. Direct port forwarding is also
+named local port forwardind, and reverse port forwarding is also called
+remote port forwarding.
+
+
+
+@subsection forwarding_direct Direct port forwarding
+
+Direct port forwarding is from client to server. The client opens a tunnel,
+and forwards whatever data to the server. Then, the server connects to an
+end point. The end point can reside on another machine or on the SSH
+server itself.
+
+Example of use of direct port forwarding:
+@verbatim
+Mail client application Google Mail
+ | ^
+ 5555 (arbitrary) |
+ | 143 (IMAP2)
+ V |
+ SSH client =====> SSH server
+
+Legend:
+--P-->: port connexion through port P
+=====>: SSH tunnel
+@endverbatim
+A mail client connects to port 5555 of a client. An encrypted tunnel is
+established to the server. The server connects to port 143 of Google Mail (the
+end point). Now the local mail client can retreive mail.
+
+
+@subsection forwarding_reverse Reverse port forwarding
+
+The reverse forwarding is slightly different. It goes from server to client,
+even though the client has the initiative of establishing the tunnel.
+Once the tunnel is established, the server will listen on a port. Whenever
+a connection to this port is made, the server forwards the data to the client.
+
+Example of use of reverse port forwarding:
+@verbatim
+ Local mail server Mail client application
+ ^ |
+ | 5555 (arbitrary)
+ 143 (IMAP2) |
+ | V
+ SSH client <===== SSH server
+
+Legend:
+--P-->: port connexion through port P
+=====>: SSH tunnel
+@endverbatim
+In this example, the SSH client establishes the tunnel,
+but it is used to forward the connections established at
+the server to the client.
+
+*** To be written ***
+
+*/
diff --git a/doc/guided_tour.dox b/doc/guided_tour.dox
index 3d41a3b8..5f7a1003 100644
--- a/doc/guided_tour.dox
+++ b/doc/guided_tour.dox
@@ -36,9 +36,6 @@ A SSH session goes through the following steps:
The sftp and scp subsystems use channels, but libssh hides them to
the programmer. If you want to use those subsystems, instead of a channel,
you'll usually open a "sftp session" or a "scp session".
-
-All the libssh functions which return an error code also set an error message.
-Error codes are typically SSH_ERROR for integer values, or NULL for pointers.
@subsection setup Creating the session and setting options
@@ -418,12 +415,41 @@ int show_remote_processes(ssh_session session)
}
@endcode
-That's the end of our step-by-step discovery of a SSH connection.
-The next chapter describes more in depth the authentication mechanisms.
-
@see @ref opening_shell
@see @ref remote_commands
@see @ref sftp_subsystem
@see @ref scp_subsystem
+
+@subsection errors Handling the errors
+
+All the libssh functions which return an error value also set an English error message
+describing the problem.
+
+Error values are typically SSH_ERROR for integer values, or NULL for pointers.
+
+The function ssh_get_error() returns a pointer to the static error message.
+
+ssh_error_code() returns the error code number : SSH_NO_ERROR,
+SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
+or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
+request, but the situation is recoverable. The others mean something happened
+to the connection (some encryption problems, server problems, ...).
+SSH_INVALID_REQUEST means the library got some garbage from server, but
+might be recoverable. SSH_FATAL means the connection has an important
+problem and isn't probably recoverable.
+
+Most of time, the error returned are SSH_FATAL, but some functions
+(generaly the ssh_request_xxx ones) may fail because of server denying request.
+In these cases, SSH_REQUEST_DENIED is returned.
+
+ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
+That's for thread safety, error messages that can be attached to a session
+aren't static anymore. Any error that happens during ssh_options_xxx()
+or ssh_connect() (i.e., outside of any session) can be retrieved by
+giving NULL as argument.
+
+The SFTP subsystem has its own error codes, in addition to libssh ones.
+
+
*/
diff --git a/doc/introduction.dox b/doc/introduction.dox
index 9026a9d1..4c51d140 100644
--- a/doc/introduction.dox
+++ b/doc/introduction.dox
@@ -41,6 +41,8 @@ Table of contents:
@subpage scp
+@subpage forwarding
+
@subpage tbd
*/
diff --git a/doc/scp.dox b/doc/scp.dox
index 811b51fd..fdf589eb 100644
--- a/doc/scp.dox
+++ b/doc/scp.dox
@@ -2,6 +2,256 @@
@page scp Chapter 6: The SCP subsystem
@section scp_subsystem The SCP subsystem
-*** To be written ***
+The SCP subsystem has far less functionnality than the SFTP subsystem.
+However, if you only need to copy files from and to the remote system,
+it does its job.
+
+
+@subsection scp_session Opening and closing a SCP session
+
+Like in the SFTP subsystem, you don't handle the SSH channels directly.
+Instead, you open a "SCP session".
+
+When you open your SCP session, you have to choose between read or write mode.
+You can't do both in the same session. So you specify either SSH_SCP_READ or
+SSH_SCP_WRITE as the second parameter of function ssh_scp_new().
+
+Another important mode flag for opening your SCP session is SSH_SCP_RECURSIVE.
+When you use SSH_SCP_RECURSIVE, you declare that you are willing to emulate
+the behaviour of "scp -r" command in your program, no matter it is for
+reading or for writing.
+
+Once your session is created, you initialize it with ssh_scp_init(). When
+you have finished transferring files, you terminate the SCP connection with
+ssh_scp_close(). Finally, you can dispose the SCP connection with
+ssh_scp_free().
+
+The example below does the maintenance work to open a SCP connection for writing in
+recursive mode:
+
+@code
+int scp_write(ssh_session session)
+{
+ ssh_scp scp;
+ int rc;
+
+ scp = ssh_scp_new
+ (session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
+ if (scp == NULL)
+ {
+ fprintf(stderr, "Error allocating scp session: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+
+ rc = ssh_scp_init(scp);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session));
+ ssh_scp_free(scp);
+ return rc;
+ }
+
+ ...
+
+ ssh_scp_close(scp);
+ ssh_scp_free(scp);
+ return SSH_OK;
+}
+@endcode
+
+The example below shows how to open a connection to read a single file:
+
+@code
+int scp_read(ssh_session session)
+{
+ ssh_scp scp;
+ int rc;
+
+ scp = ssh_scp_new
+ (session, SSH_SCP_READ, "helloworld/helloworld.txt");
+ if (scp == NULL)
+ {
+ fprintf(stderr, "Error allocating scp session: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+
+ rc = ssh_scp_init(scp);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session));
+ ssh_scp_free(scp);
+ return rc;
+ }
+
+ ...
+
+ ssh_scp_close(scp);
+ ssh_scp_free(scp);
+ return SSH_OK;
+}
+
+@endcode
+
+
+@subsection scp_write Creating files and directories
+
+You create directories with ssh_scp_push_directory(). In recursive mode,
+you are placed in this directory once it is created. If the directory
+already exists and if you are in recursive mode, you simply enter that
+directory.
+
+Creating files is done in two steps. First, you prepare the writing with
+ssh_scp_push_file(). Then, you write the data with ssh_scp_write().
+The length of the data to write must be identical between both function calls.
+There's no need to "open" nor "close" the file, this is done automatically
+on the remote end. If the file already exists, it is overwritten and truncated.
+
+The following example creates a new directory named "helloworld/", then creates
+a file named "helloworld.txt" in that directory:
+
+@code
+int scp_helloworld(ssh_session session, ssh_scp scp)
+{
+ int rc;
+ const char *helloworld = "Hello, world!\n";
+ int length = strlen(helloworld);
+
+ rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Can't create remote directory: %s\n", ssh_get_error(session));
+ return rc;
+ }
+
+ rc = ssh_scp_push_file
+ (scp, "helloworld.txt", length, S_IRUSR | S_IWUSR);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Can't open remote file: %s\n", ssh_get_error(session));
+ return rc;
+ }
+
+ rc = ssh_scp_write(scp, helloworld, length);
+ if (rc != SSH_OK)
+ {
+ fprintf(stderr, "Can't write to remote file: %s\n", ssh_get_error(session));
+ return rc;
+ }
+
+ return SSH_OK;
+}
+@endcode
+
+
+@subsection scp_recursive_write Copying full directory trees to the remote server
+
+Let's say you want to copy the following tree of files to the remote site:
+
+@verbatim
+ +-- file1
+ +-- B --+
+ | +-- file2
+-- A --+
+ | +-- file3
+ +-- C --+
+ +-- file4
+@endverbatim
+
+You would do it that way:
+ - open the session in recursive mode
+ - enter directory A
+ - enter its subdirectory B
+ - create file1 in B
+ - create file2 in B
+ - leave directory B
+ - enter subdirectory C
+ - create file3 in C
+ - create file4 in C
+ - leave directory C
+ - leave directory A
+
+To leave a directory, call ssh_scp_leave_directory().
+
+
+@subsection scp_read Reading files and directories
+
+
+To receive files, you pull requests from the other side with ssh_scp_pull_request().
+If this function returns SSH_SCP_REQUEST_NEWFILE, then you must get ready for
+the reception. You can get the size of the data to receive with ssh_scp_request_get_size()
+and allocate a buffer accordingly. When you are ready, you accept the request with
+ssh_scp_accept_request(), then read the data with ssh_scp_read().
+
+The following example receives a single file. The name of the file to
+receive has been given earlier, when the scp session was opened:
+
+@code
+int scp_receive(ssh_session session, ssh_scp scp)
+{
+ int rc;
+ int size, mode;
+ char *filename, *buffer;
+
+ rc = ssh_scp_pull_request(scp);
+ if (rc != SSH_SCP_REQUEST_NEWFILE)
+ {
+ fprintf(stderr, "Error receiving information about file: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+
+ size = ssh_scp_request_get_size(scp);
+ filename = strdup(ssh_scp_request_get_filename(scp));
+ mode = ssh_scp_request_get_permissions(scp);
+ printf("Receiving file %s, size %d, permisssions 0%o\n", filename, size, mode);
+ free(filename);
+
+ buffer = malloc(size);
+ if (buffer == NULL)
+ {
+ fprintf(stderr, "Memory allocation error\n");
+ return SSH_ERROR;
+ }
+
+ ssh_scp_accept_request(scp);
+ rc = ssh_scp_read(scp, buffer, size);
+ if (rc == SSH_ERROR)
+ {
+ fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(session));
+ free(buffer);
+ return rc;
+ }
+ printf("Done\n");
+
+ write(1, buffer, size);
+ free(buffer);
+
+ rc = ssh_scp_pull_request(scp);
+ if (rc != SSH_SCP_REQUEST_EOF)
+ {
+ fprintf(stderr, "Unexpected request: %s\n", ssh_get_error(session));
+ return SSH_ERROR;
+ }
+
+ return SSH_OK;
+}
+@endcode
+
+In this example, since we just requested a single file, we expect ssh_scp_request()
+to return SSH_SCP_REQUEST_NEWFILE first, then SSH_SCP_REQUEST_EOF. That's quite a
+naive approach; for example, the remote server might send a warning as well
+(return code SSH_SCP_REQUEST_WARNING) and the example would fail. A more comprehensive
+reception program would receive the requests in a loop and analyze them carefully
+until SSH_SCP_REQUEST_EOF has been received.
+
+
+@subsection scp_recursive_read Receiving full directory trees from the remote server
+
+If you opened the SCP session in recursive mode, the remote end will be
+telling you when to change directory.
+
+In that case, when ssh_scp_pull_request() answers
+SSH_SCP_REQUEST_NEWDIRECTORY, you should make that local directory (if
+it does not exist yet) and enter it. When ssh_scp_pull_request() answers
+SSH_SCP_REQUEST_ENDDIRECTORY, you should leave the current directory.
*/
diff --git a/doc/sftp.dox b/doc/sftp.dox
index 6f9bcde7..7306be57 100644
--- a/doc/sftp.dox
+++ b/doc/sftp.dox
@@ -29,7 +29,7 @@ The current implemented version of the SFTP protocol is version 3. All functions
aren't implemented yet, but the most important are.
-@subsection sftp_section Opening and closing a SFTP session
+@subsection sftp_session Opening and closing a SFTP session
Unlike with remote shells and remote commands, when you use the SFTP subsystem,
you don't handle directly the SSH channels. Instead, you open a "SFTP session".
diff --git a/doc/tbd.dox b/doc/tbd.dox
index 4ee5ab84..1e256fdb 100644
--- a/doc/tbd.dox
+++ b/doc/tbd.dox
@@ -1,40 +1,9 @@
/**
@page tbd To be done
-@section errors Handling the errors
-
-When some function returns an error code, it's always possible to get an
-english message describing the problem.
-
-The function ssh_get_error() returns a pointer to the static error buffer.
-
-ssh_error_code() returns the error code number : SSH_NO_ERROR,
-SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
-or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
-request, but the situation is recoverable. The others mean something happened
-to the connection (some encryption problems, server problems, ...).
-SSH_INVALID_REQUEST means the library got some garbage from server, but
-might be recoverable. SSH_FATAL means the connection has an important
-problem and isn't probably recoverable.
-
-Most of time, the error returned are SSH_FATAL, but some functions
-(generaly the ssh_request_xxx ones) may fail because of server denying request.
-In these cases, SSH_REQUEST_DENIED is returned.
-
-ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
-That's for thread safety, error messages that can be attached to a session
-aren't static anymore. Any error that happens during ssh_options_xxx()
-or ssh_connect() (i.e., outside of any session) can be retrieved by
-giving NULL as argument.
-
-
@section threads Working with threads
*** To be written ***
-@section forwarding_connections Forwarding connections
-
-*** To be written ***
-
@section sshd Writing a libssh-based server
*** To be written ***