tcpproto

package module
v1.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 15, 2022 License: GPL-2.0 Imports: 24 Imported by: 0

README

tcpproto

Simple http-like layer ontop of TCP.

This layer is capable of transfering files, authentication, client-side storage and more!

Usage:

  • First, inititalize the CONFIG like so:
func InitConfig(secret_key string, loglevel string, buff_size int, use_crypto bool, include_sysinfo bool, authenticate func(rq *Request, resp *Response) error) *Config {
	return &Config{
		SecretKey:       secret_key,
		LOGGER:          NewLogger(loglevel),
		BUFF_SIZE:       buff_size,
		Include_Sysinfo: include_sysinfo,
		Default_Auth:    authenticate,
		Use_Crypto:      use_crypto,
	}
}

tcpproto.InitConfig("secret_key", "debug", 1024, true, true, func(rq *Request, resp *Response) error {
	// Do authentication here
	return nil
})

Then we can get to start sending requests. A typical response/request looks like this:

CONTENT_LENGTH: CONTENT_LENGTH int
COMMAND: COMMAND string
CUSTOM_HEADER: CUSTOM_HEADER string
CUSTOM_HEADER: CUSTOM_HEADER string
CUSTOM_HEADER: CUSTOM_HEADER string
CUSTOM_HEADER: CUSTOM_HEADER string
HAS_FILE: HAS_FILE bool
FILE_NAME: FILE_NAME string
FILE_SIZE: FILE_SIZE int
FILE_BOUNDARY: FILE_BOUNDARY string

FILE_BOUNDARY
FILE CONTENT
FILE CONTENT
FILE CONTENT
FILE_BOUNDARY

CONTENT CONTENT CONTENT
CONTENT CONTENT CONTENT
CONTENT CONTENT CONTENT

Where anything that has to do with files, can optionally be left out.
To add a file, you can use the following:

request.AddFile(filename string, content []byte, boundary string)

The following is needed:
CONTENT_LENGTH and COMMAND
Content length is used to make sure the whole request is parsed properly, and chunks we not forgotten.
Command is used to add callbacks to the request/response cycle, where you can edit either one.

Server

A typical server looks like this:

func main() {
	ipaddr := "127.0.0.1"
	port := 22392
	// If CONF.Use_Crypto is disabled, you do not have to provide the private RSA key,
	// it can be left as an empty string.
	s := tcpproto.InitServer(ipaddr, port, "PRIVATE_KEY.pem")
	s.AddMiddlewareBeforeResp(AuthMiddleware) // Middleware to be called before the callback is called.
	s.AddMiddlewareAfterResp(tcpproto.LogMiddleware) // Middleware to be called after the callback is called.
	s.AddCallback("SET", SET) // The callback to be called, derived from "COMMAND" header.
	s.AddCallback("GET", GET)
	if err := s.Start(); err != nil {
		os.Exit(1)
	}
}
Middleware

To add middleware, or callbacks, the function needs to take the following arguments:

func MiddlewareOrCallback(rq *tcpproto.Request, resp *tcpproto.Response){
	// Do stuff here
}

In these middleware and callbacks you can ofcourse access all headers with request.Headers (Cookies are also stored here) Or optionally, you can encrypt data with the SECRET_KEY provided to the CONFIG.

Storing data client side

This data is then sent, like HTTP cookies, on every request. To encrypt data, you can use the following:

response.Lock(key string, data string)

To set some cookies in the response, you can use the following:

response.Remember(key string, data string)

To remove the encrypted data from the client

response.ForgetVault(key string)

To remove a cookie from the client

response.Forget(key string)
Client information

If you have enabled Include_Sysinfo in the CONFIG, you can access the following method in on the request:

var system_information tcpproto.SysInfo
system_information = request.SysInfo()

You then have access to the following information:

system_information.Hostname 	// The hostname of the client
system_information.Platform 	// The platform of the client
system_information.CPU 			// The CPU of the client
system_information.RAM 			// The RAM of the client
system_information.Disk 		// The disk of the client
system_information.MacAddr 		// The MAC address of the client

Client:

A typical client looks like this:

// Initialise request
request := InitRequest()

// Set some headers
// CONTENT_LENGTH is automatically added when generating the request.
request.Headers["COMMAND"] = "SET"
request.Headers["HEADER-TEST-1"] = "VALUE-TEST-1" 
request.Headers["HEADER-TEST-2"] = "VALUE-TEST-2" 
request.Headers["HEADER-TEST-3"] = "VALUE-TEST-3" 

// Set request content
request.Content = []byte("TEST_CONTENT\n")

// Initialize client
// If CONF.Use_Crypto is disabled, you do not have to provide the public RSA key,
// it can be left as an empty string.
client := InitClient("127.0.0.1", 12239, "PUBLIKKEY.pem")

// Connect to server
if err := client.Connect(); err != nil {
	err = errors.New("error connecting to server: " + err.Error())
	t.Error(err)
}

// Set some "cookies"
client.Cookies["TEST0"] = InitCookie("TEST0", "TEST0")

// Add something to the client side vault, this is encrypted with a public key, and decrypted by the server. 
// This only works if CONF.Use_Crypto is enabled.
client.Vault("Cookiename", "Cookievalue")

// Get the response when sending the data to the server
response, err = client.Send(request)
if err != nil {
	err = errors.New("error sending request: " + err.Error())
	t.Error(err)
}
// Close the client when done
if err := client.Close(); err != nil {
	err = errors.New("error closing client connection: " + err.Error())
	t.Error(err)
}

As you can see, the client receives the response back when sending data to a server. This data fits into the following struct:

// Response the server sends back
type Response struct {
	Headers   map[string]string
	SetValues map[string]string
	DelValues []string
	Vault     map[string]string
	Content   []byte
	File      *FileData
	Error     []error
}

// Request to send to the server
type Request struct {
	Headers            map[string]string
	Vault              map[string]string
	Content            []byte
	File               *FileData
	Data               map[string]string
	User               *User
	Conn               net.Conn
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CONF = InitConfig("SECRET_KEY", "DEBUG", 2048, false, true, Authenticate)

Functions

func Authenticate

func Authenticate(rq *Request, resp *Response) error

func Base64ToBytes

func Base64ToBytes(s string) []byte

func Base64ToKey

func Base64ToKey(s string) *[32]byte

func BytesToBase64

func BytesToBase64(b []byte) string

func Colorize

func Colorize(level int, msg string) string

func Decrypt

func Decrypt(ciphertext []byte, key *[32]byte) (plaintext []byte, err error)

Decrypt decrypts data using 256-bit AES-GCM. This both hides the content of the data and provides a check that it hasn't been altered. Expects input form nonce|ciphertext|tag where '|' indicates concatenation.

func DecryptString

func DecryptString(s string, key *[32]byte) (string, error)

func DecryptWithPrivateKey

func DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) []byte

DecryptWithPrivateKey decrypts data with private key

func Encrypt

func Encrypt(plaintext []byte, key *[32]byte) (ciphertext []byte, err error)

Encrypt encrypts data using 256-bit AES-GCM. This both hides the content of the data and provides a check that it hasn't been altered. Output takes the form nonce|ciphertext|tag where '|' indicates concatenation.

func EncryptString

func EncryptString(s string, key *[32]byte) (string, error)

func EncryptWithPublicKey

func EncryptWithPublicKey(msg []byte, pub *rsa.PublicKey) []byte

EncryptWithPublicKey encrypts data with public key

func ExportPrivate_PEM_Key

func ExportPrivate_PEM_Key(key *rsa.PrivateKey, filename string)

func ExportPublic_PEM_Key

func ExportPublic_PEM_Key(key *rsa.PublicKey, filename string)

func GenerateKeyPair

func GenerateKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey)

func GetMACAddr

func GetMACAddr() (string, error)

func ImportPrivate_PEM_Key

func ImportPrivate_PEM_Key(filename string) *rsa.PrivateKey

func ImportPublic_PEM_Key

func ImportPublic_PEM_Key(filename string) *rsa.PublicKey

func KeyToBase64

func KeyToBase64(key *[32]byte) string

func LogMiddleware

func LogMiddleware(rq *Request, resp *Response)

func NewEncryptionKey

func NewEncryptionKey() *[32]byte

NewEncryptionKey generates a random 256-bit key for Encrypt() and Decrypt(). It panics if the source of randomness fails.

func PadStr

func PadStr(s string, l int) string

func PrivKeySTR_to_PrivKey

func PrivKeySTR_to_PrivKey(privkeystr string) *rsa.PrivateKey

func PubKeySTR_to_PubKey

func PubKeySTR_to_PubKey(pubkeystr string) *rsa.PublicKey

func TransferValues

func TransferValues(rq *Request, resp *Response)

func TrimExtraSpaces

func TrimExtraSpaces(s string) string

func UnpadStr

func UnpadStr(s string) string

func WrapTime

func WrapTime(t string, msg string) string

Types

type Client

type Client struct {
	IP          string
	Port        int
	Conn        net.Conn
	Cookies     map[string]*Cookie
	ClientVault map[string]string
	PUBKEY      *rsa.PublicKey
}

func InitClient

func InitClient(ip string, port int, pubkey_file string) *Client

func (*Client) Addr

func (c *Client) Addr() string

func (*Client) Close

func (c *Client) Close() error

func (*Client) Connect

func (c *Client) Connect() error

func (*Client) ParseResponse

func (c *Client) ParseResponse(rq *Request, header map[string]string, recv_data []byte) (*Response, error)

func (*Client) Send

func (c *Client) Send(rq *Request) (*Response, error)

func (*Client) UpdateCookies

func (c *Client) UpdateCookies(remember map[string]string, forget []string)

func (*Client) Vault

func (c *Client) Vault(key string, value string) error

type Config

type Config struct {
	SecretKey       string
	LOGGER          *Logger
	BUFF_SIZE       int
	Default_Auth    func(rq *Request, resp *Response) error
	Include_Sysinfo bool
	Use_Crypto      bool
}

func GetConfig

func GetConfig() *Config

func InitConfig

func InitConfig(secret_key string, loglevel string, buff_size int, use_crypto bool, include_sysinfo bool, authenticate func(rq *Request, resp *Response) error) *Config

func SetConfig

func SetConfig(secret_key string, loglevel string, buff_size int, use_crypto bool, include_sysinfo bool, authenticate func(rq *Request, resp *Response) error) *Config

func (*Config) GenVault

func (c *Config) GenVault(key string, value string) (string, error)

func (*Config) GetVault

func (c *Config) GetVault(value string) (string, string, bool)
type Cookie struct {
	Name  string
	Value string
}

func InitCookie

func InitCookie(name string, value string) *Cookie

type Cookies

type Cookies struct {
	// contains filtered or unexported fields
}

func InitCookies

func InitCookies() *Cookies

func (*Cookies) AddCookie

func (c *Cookies) AddCookie(cookie *Cookie)

func (*Cookies) GetCookie

func (c *Cookies) GetCookie(name string) *Cookie

type FileData

type FileData struct {
	Name     string
	Size     int
	Boundary string
	Present  bool
	Content  []byte
}

func (*FileData) EndBoundary

func (fdata *FileData) EndBoundary() []byte

func (*FileData) StartBoundary

func (fdata *FileData) StartBoundary() []byte

type Logger

type Logger struct {
	Level string `json:"level"`
}

func NewLogger

func NewLogger(level string) *Logger

func (*Logger) Debug

func (l *Logger) Debug(msg string)

func (*Logger) Error

func (l *Logger) Error(msg string)

func (*Logger) GetLevel

func (l *Logger) GetLevel() int

func (*Logger) GetLevelFromType

func (l *Logger) GetLevelFromType(t string) int

func (*Logger) Info

func (l *Logger) Info(msg string)

func (*Logger) Test

func (l *Logger) Test(msg string)

func (*Logger) Warning

func (l *Logger) Warning(msg string)

func (*Logger) Write

func (l *Logger) Write(t string, msg string)

type Middleware

type Middleware struct {
	BeforeResponse func(rq *Request, resp *Response)
	AfterResponse  func(rq *Request, resp *Response)
	Before         bool
}

type Request

type Request struct {
	Headers map[string]string
	Vault   map[string]string
	Content []byte
	File    *FileData
	Data    map[string]string
	User    *User
	Conn    net.Conn
	// contains filtered or unexported fields
}

func InitRequest

func InitRequest() *Request

func (*Request) AddCookie

func (rq *Request) AddCookie(key string, value string)

func (*Request) AddFile

func (rq *Request) AddFile(filename string, file []byte, boundary string)

func (*Request) AddHeader

func (rq *Request) AddHeader(key string, value string)

func (*Request) ContentLength

func (rq *Request) ContentLength() int

func (*Request) DecryptVault

func (rq *Request) DecryptVault() map[string]string

func (*Request) Generate

func (rq *Request) Generate() ([]byte, error)

func (*Request) MacAddr

func (rq *Request) MacAddr() string

func (*Request) ParseFile

func (rq *Request) ParseFile() error

func (*Request) ParseFileData

func (rq *Request) ParseFileData() ([]byte, error)

func (*Request) SysInfo

func (rq *Request) SysInfo() *SysInfo

type Response

type Response struct {
	Headers   map[string]string
	SetValues map[string]string
	DelValues []string
	Vault     map[string]string
	Content   []byte
	File      *FileData
	Error     []error
}

func InitResponse

func InitResponse() *Response

func (*Response) AddError

func (resp *Response) AddError(err string)

func (*Response) AddFile

func (resp *Response) AddFile(filename string, file []byte, boundary string)

func (*Response) Bytes

func (resp *Response) Bytes() []byte

func (*Response) ContentLength

func (resp *Response) ContentLength() int

func (*Response) DecodeHeaders

func (resp *Response) DecodeHeaders(headers map[string]string) (map[string]string, []string, error)

func (*Response) Forget

func (resp *Response) Forget(key string) *Response

func (*Response) ForgetVault

func (resp *Response) ForgetVault(key string)

func (*Response) GenHeader

func (resp *Response) GenHeader() string

func (*Response) Generate

func (resp *Response) Generate() []byte

func (*Response) GetVault

func (resp *Response) GetVault(key string) (string, bool)

func (*Response) Lock

func (resp *Response) Lock(key string, value string) *Response

func (*Response) ParseFile

func (resp *Response) ParseFile() error

func (*Response) ParseFileData

func (resp *Response) ParseFileData() ([]byte, error)

func (*Response) Remember

func (resp *Response) Remember(k string, v string) *Response

type Server

type Server struct {
	IP         string
	Config     *Config
	Port       int
	Callbacks  map[string]func(rq *Request, resp *Response)
	Middleware []*Middleware
	PRIVKEY    *rsa.PrivateKey
	// contains filtered or unexported fields
}

func InitServer

func InitServer(ip string, port int, privkey_file string) *Server

func (*Server) AddCallback

func (s *Server) AddCallback(key string, callback func(rq *Request, resp *Response))

Add a COMMAND callback to the server

func (*Server) AddMiddlewareAfterResp

func (s *Server) AddMiddlewareAfterResp(middleware func(rq *Request, resp *Response))

Middleware to be used after the response is created

func (*Server) AddMiddlewareBeforeResp

func (s *Server) AddMiddlewareBeforeResp(middleware func(rq *Request, resp *Response))

Middleware to be used before the response is created

func (*Server) Addr

func (s *Server) Addr() string

func (*Server) DecryptClientVault

func (s *Server) DecryptClientVault(rq *Request) error

func (*Server) ExecCallback

func (s *Server) ExecCallback(rq *Request, resp *Response) error

Execute the callback for the given request

func (*Server) MiddlewareAfterResponse

func (s *Server) MiddlewareAfterResponse(rq *Request, resp *Response)

Execute middleware after the response is created

func (*Server) MiddlewareBeforeResponse

func (s *Server) MiddlewareBeforeResponse(rq *Request, resp *Response)

Execute middleware before the response is created

func (*Server) ParseConnection

func (s *Server) ParseConnection(conn net.Conn) (*Request, *Response, error)

func (*Server) Send

func (s *Server) Send(conn net.Conn, resp *Response) error

func (*Server) Serve

func (s *Server) Serve() error

func (*Server) Start

func (s *Server) Start() error

type SysInfo

type SysInfo struct {
	Hostname string `json:"hostname"`
	Platform string `json:"platform"`
	CPU      string `json:"cpu"`
	RAM      uint64 `json:"ram"`
	Disk     uint64 `json:"disk"`
	MacAddr  string `json:"macaddr"`
}

SysInfo saves the basic system information

func GetSysInfo

func GetSysInfo() *SysInfo

func (*SysInfo) ToJSON

func (s *SysInfo) ToJSON() string

type User

type User struct {
	ID              int
	Username        string
	Email           string
	Password        string
	IsAdmin         bool
	IsAuthenticated bool
	SysInfo         *SysInfo
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL