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
2015-01-23 17:24:36 +01:00

180 lines
6.4 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
/**
* --------------------------------------------------------------------------------------------------------------------------
* Come funziona ssh:
* --------------------------------------------------------------------------------------------------------------------------
* Ogni host su cui è installato ssh possiede una coppia di chiavi RSA (un algoritmo di crittografia a chiave asimmetrica)
* lunghe 1024 bit, una pubblica ed una privata. In più, ogni utente che utilizza ssh può opzionalmente generare una propria
* coppia di chiavi RSA. All'atto della connessione, il server comunica al client due chiavi pubbliche: una fissa di 1024 bit
* che è la vera e propria chiave dell'host e l'altra di 768 bit che viene rigenerata ogni ora. Il client allora genera una
* sequenza casuale di 256 bit e la codifica con le chiavi pubbliche del server. Da questo momento in poi la connessione viene
* crittografata con uno degli algoritmi a chiave simmetrica supportati da ssh (IDEA, DES, 3DES, Arcfour, Blowfish) e si passa
* alla fase di autenticazione.
* --------------------------------------------------------------------------------------------------------------------------
* 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:
// COSTRUTTORI
USSHSocket(bool bSocketIsIPv6 = false) : USocket(bSocketIsIPv6)
{
U_TRACE_REGISTER_OBJECT(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_UNREGISTER_OBJECT(0, USSHSocket)
close();
if (buffer) U_SYSCALL_VOID(buffer_free, "%p", buffer);
}
// VARIE
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(1, "USSHSocket::sendEOF()")
U_INTERNAL_ASSERT_POINTER(channel)
U_SYSCALL_VOID(channel_send_eof, "%p", channel);
}
// VIRTUAL METHOD
/**
* 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:
#ifdef U_COMPILER_DELETE_MEMBERS
USSHSocket(const USSHSocket&) = delete;
USSHSocket& operator=(const USSHSocket&) = delete;
#else
USSHSocket(const USSHSocket&) : USocket(false) {}
USSHSocket& operator=(const USSHSocket&) { return *this; }
#endif
};
#endif