#ifndef PACKETPP_SSH_LAYER
#define PACKETPP_SSH_LAYER
#include "Layer.h"
namespace pcpp
{
class SSHLayer : public Layer
{
public:
static SSHLayer* createSSHMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
static bool isSSHPort(uint16_t portSrc, uint16_t portDst) { return portSrc == 22 || portDst == 22; }
void parseNextLayer();
void computeCalculateFields() {}
OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
protected:
SSHLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = SSH; }
private:
SSHLayer();
};
class SSHIdentificationMessage : public SSHLayer
{
public:
std::string getIdentificationMessage();
static SSHIdentificationMessage* tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
size_t getHeaderLen() const { return m_DataLen; }
std::string toString() const;
private:
SSHIdentificationMessage();
SSHIdentificationMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {}
};
class SSHHandshakeMessage : public SSHLayer
{
public:
enum SSHHandshakeMessageType
{
SSH_MSG_KEX_INIT = 20,
SSH_MSG_NEW_KEYS = 21,
SSH_MSG_KEX_DH_INIT = 30,
SSH_MSG_KEX_DH_REPLY = 31,
SSH_MSG_KEX_DH_GEX_INIT = 32,
SSH_MSG_KEX_DH_GEX_REPLY = 33,
SSH_MSG_KEX_DH_GEX_REQUEST = 34,
SSH_MSG_UNKNOWN = 999
};
SSHHandshakeMessageType getMessageType() const;
std::string getMessageTypeStr() const;
uint8_t* getSSHHandshakeMessage() const;
size_t getSSHHandshakeMessageLength() const;
size_t getPaddingLength() const;
static SSHHandshakeMessage* tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
size_t getHeaderLen() const;
std::string toString() const;
protected:
#pragma pack(push, 1)
struct ssh_message_base
{
uint32_t packetLength;
uint8_t paddingLength;
uint8_t messageCode;
};
#pragma pack(pop)
SSHHandshakeMessage();
SSHHandshakeMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {}
ssh_message_base* getMsgBaseHeader() const { return (ssh_message_base*)m_Data; }
};
class SSHKeyExchangeInitMessage : public SSHHandshakeMessage
{
public:
SSHKeyExchangeInitMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
uint8_t* getCookie();
std::string getCookieAsHexStream();
std::string getKeyExchangeAlgorithms() { return getFieldValue(0); }
std::string getServerHostKeyAlgorithms() { return getFieldValue(1); }
std::string getEncryptionAlgorithmsClientToServer() { return getFieldValue(2); }
std::string getEncryptionAlgorithmsServerToClient() { return getFieldValue(3); }
std::string getMacAlgorithmsClientToServer() { return getFieldValue(4); }
std::string getMacAlgorithmsServerToClient() { return getFieldValue(5); }
std::string getCompressionAlgorithmsClientToServer() { return getFieldValue(6); }
std::string getCompressionAlgorithmsServerToClient() { return getFieldValue(7); }
std::string getLanguagesClientToServer() { return getFieldValue(8); }
std::string getLanguagesServerToClient() { return getFieldValue(9); }
bool isFirstKexPacketFollows();
private:
size_t m_FieldOffsets[11];
bool m_OffsetsInitialized;
void parseMessageAndInitOffsets();
std::string getFieldValue(int fieldOffsetIndex);
};
class SSHEncryptedMessage : public SSHLayer
{
public:
SSHEncryptedMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {}
size_t getHeaderLen() const { return m_DataLen; }
std::string toString() const;
};
}
#endif