1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/include/ulib/ssh/net/sshsocket.h
stefanocasazza 1e58dc49d0 fix+sync
2018-04-27 19:27:14 +02:00

158 lines
5.1 KiB
C++

// ============================================================================
//
// = LIBRARY
// ULib - c++ library
//
// = FILENAME
// sshsocket.h
//
// = AUTHOR
// Stefano Casazza
//
// ============================================================================
#ifndef ULIB_SSHSOCKET_H
#define ULIB_SSHSOCKET_H 1
#include <ulib/net/socket.h>
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#undef PACKAGE_BUGREPORT
#include <libssh/libssh.h>
#undef PACKAGE_NAME
#define PACKAGE_NAME "ULib"
#undef PACKAGE_VERSION
#define PACKAGE_VERSION ULIB_VERSION
/**
* --------------------------------------------------------------------------------------------------------------------------
* The SSH protocol was designed for some goals which I resume here:
*
* a) Privacy of data
* b) Security
* c) Authentication of the server
* d) Authentication of the client
*
* The client MUST be sure who's speaking to before entering into any authentication way. That's where the end programmer must
* ensure the given fingerprints *are* from the legitimate server. A ssh connection must follow the following steps:
*
* 1) Before connecting the socket, you can set up if you wish one or other server public key authentication ie. DSA or RSA.
* You can choose cryptographic algorithms you trust and compression algorithms if any
* 2) The connection is made. A secure handshake is made, and resulting from it, a public key from the server is gained.
* You MUST verify that the public key is legitimate
* 3) The client must authenticate: the two implemented ways are password, and public keys (from dsa and rsa key-pairs
* generated by openssh). It is harmless to authenticate to a fake server with these keys because the protocol ensures
* the data you sign can't be used twice. It just avoids man-in-the-middle attacks
* 4) Now that the user has been authenticated, you must open one or several channels. channels are different subways for
* information into a single ssh connection. Each channel has a standard stream (stdout) and an error stream (stderr).
* You can theoretically open an infinity of channel
* 5) With the channel you opened, you can do several things:
* - Open a shell. You may want to request a pseudo virtual terminal before
* - Execute a command. The virtual terminal is usable, too
* - Invoke the sftp subsystem. (look at chapter 6)
* - invoke your own subsystem. This is out the scope of this document but it is easy to do
* 6) When everything is finished, just close the channels, and then the connection
* ---------------------------------------------------------------------------------------------------------------------------
*/
class U_EXPORT USSHSocket : public USocket {
public:
USSHSocket(bool bSocketIsIPv6 = false) : USocket(bSocketIsIPv6)
{
U_TRACE_CTOR(0, USSHSocket, "%b", bSocketIsIPv6)
buffer = 0;
channel = 0;
ret = auth = 0;
user = public_key = private_key = 0;
session = (ssh_session) U_SYSCALL_NO_PARAM(ssh_new);
}
~USSHSocket()
{
U_TRACE_DTOR(0, USSHSocket)
close();
if (buffer) U_SYSCALL_VOID(buffer_free, "%p", buffer);
}
void close();
bool setError();
bool SSHConnection(int fd);
void setUser(const char* _user)
{
U_TRACE(1, "USSHSocket::setUser(%S)", _user)
U_INTERNAL_ASSERT_POINTER(_user)
user = _user;
(void) U_SYSCALL(ssh_options_set, "%p,%d,%S", session, SSH_OPTIONS_USER, user);
}
void setKey(const char* _private_key = "/%U/.ssh/id_rsa",
const char* _public_key = "/%U/.ssh/id_rsa.pub")
{
U_TRACE(1, "USSHSocket::setKey(%S,%S)", _private_key, _public_key)
public_key = _public_key;
private_key = _private_key;
}
void setVerbosity(int num = -1)
{
U_TRACE(1, "USSHSocket::setVerbosity(%d)", num)
(void) U_SYSCALL(ssh_options_set, "%p,%d,%p", session, SSH_OPTIONS_LOG_VERBOSITY, &num);
}
void sendEOF()
{
U_TRACE_NO_PARAM(1, "USSHSocket::sendEOF()")
U_INTERNAL_ASSERT_POINTER(channel)
U_SYSCALL_VOID(channel_send_eof, "%p", channel);
}
/**
* This method is called to connect the socket to a server SSH deamon that is specified
* by the provided host name and port number. We call the ssh_connect() function to perform the connection
*/
virtual bool connectServer(const UString& server, unsigned int iServPort, int timeoutMS = 0) U_DECL_OVERRIDE; // 22
virtual int recv( void* pBuffer, uint32_t iBufLength) U_DECL_OVERRIDE;
virtual int send(const char* pPayload, uint32_t iPayloadLength) U_DECL_OVERRIDE;
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
const char* dump(bool reset) const;
#endif
protected:
const char* user;
ssh_buffer buffer;
ssh_channel channel;
ssh_session session;
const char* public_key;
const char* private_key;
int ret, auth;
void setStatus() U_NO_EXPORT;
void setStatus(int n) { ret = n; setStatus(); }
private:
U_DISALLOW_COPY_AND_ASSIGN(USSHSocket)
};
#endif