janus

package module
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Apr 23, 2024 License: Unlicense Imports: 10 Imported by: 0

README

janus

reverse-engineer from node-sds

I could not find any document describing the protocol but there is a fairly easy to read C++ library that you can use to "reverse-engineer" the protocol (You'll find it under src/janus/2.9.6/srvclnt) plus you can always analyze the TCP stream with Wireshark.

Layout of a Typical Message

The protocol seems to be modeled with RPC in mind. You have operations that are invoked with a single message that is send to the server along with a bunch of parameters. The response usually contains the return value of that operation.

╔═════ > Message Head
║ 0
║ 1  First 4-bytes are the length of the entire message in network byte order, including the length itself. It seems
║ 2  that it is possible to bit-wise OR some flags in here, but we do not do this.
║ 3
╠══
║ 0
║ 1
║ 2
║ 3  These 8 bytes are reserved for a 64-bit data structure called OID. An OID is a unique identifier (application
║ 4  wide, I guess) that identifies a single object. Rarely used here. Most of the times these are just 0-bytes.
║ 5
║ 6
║ 7
╠══
║ 0  The last byte of the message head encodes the operation used. See enum below.
╚══
╔══
║ 0  First byte of this block is the type of this parameter. See enum below.
╠══
║ 1  Second byte is the parameter name. See enum below.
╠══
║ 2
║ 3
║ 4  The remainder is the actual data of the parameter. This data block is of variable length, depending on the
║ 5  parameter type.
║ 6
║ 7
║ .
║ .
║ .
╚═════ > Message parameter

Each message possibly consists of multiple parameters. There must be at least one, I think.

There are also "simple" messages. Simple messages have no message parameters and consist solely of the message head, actually just the first four bytes of it (thus are 8-bytes in total). Simple messages are also not used here.

Saying "Hello" in SDS

Precondition: TCP connection established. A SDS connection is "established" after following sequence of messages got exchanged.

  1. We send a short "Hello"-like message.
  2. The server acknowledges this message with a short response, possibly negotiating SSL terms.
  3. We introduce ourselves by sending a short string containing our client's name.
  4. The server responds with a client ID that we store.

After that it seems that we can do pretty much what we like.

The "Hello"-like message consists of a 8-byte buffer whereas the first four bytes can be picked at random and the last four bytes are a crypt(3) with MD5 variation encrypted of the first 4 bytes. We don't bother and always send the same 8 bytes.

The client ID can be used to track this connection in the server's log files later on. I presume this client ID is solely useful for logging and debugging purposes. A connection is closed simply by ending the TCP connection (by sending a FIN packet). The server usually notes this as a "client crashed" event in the log files. However, every existing client seems to do it this way. You can use the disconnect() method for this.

TODOs

  1. TLS

missing operations

  • Systemuser.get
  • Global.doMaintenance
  • Global.importXML2
  • Global.exportXML
  • PartnerNet.getProperty
  • PartnerNet.*clearPortalScriptCache
  • PortalScript.setScriptInfoFromJSON
  • PortalScript.getScriptInfoAsJSON
  • PortalScript.downloadScript
  • PortalScript.getSourceCodeForEditor
  • PortalScript.uploadScript
  • PortalScript.runScript
  • PortalScript.debugScript
  • PortalScript.getScriptNames
  • IPortalScript.getScriptNamesWithModes
  • IDlcFileType.getFieldNames
  • IDlcFileType.getFieldNamesAndTypes
  • IDlcFileType.getRegisterNames
  • IDlcFileType.getFileTypeNames

Documentation

Index

Constants

View Source
const (
	Hello             = "GGCH$1$$"
	InitialBufferSize = 4 * 1024
	MessageHeadLength = 13
	OidLowIndex       = 4
	OidHighIndex      = 8
	OperationIndex    = 12
	FirstParamIndex   = 13
	JanusSalt         = "o3"
)
View Source
const (
	INITIAL_BUFFER_SIZE = 1024
)

Variables

View Source
var (
	Ack     = []byte("valid\x00")
	Invalid = []byte("invalid\x00")
)

Functions

This section is empty.

Types

type COMOperation

type COMOperation int32
const (
	COMOperationErrorMessage      COMOperation = 17
	COMOperationRunScriptOnServer COMOperation = 42
)

type JanusClient

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

func NewJanusClient

func NewJanusClient(addr string) (c *JanusClient, err error)

func NewJanusClientSsl

func NewJanusClientSsl(addr string) (c *JanusClient, err error)

! TODO implement ssl with certificates

func (*JanusClient) CallClassOperation

func (c *JanusClient) CallClassOperation(classAndOp string, parameters []string, parametersPDO []string) (result int32, resultList []string, err error)

func (*JanusClient) ChangePrincipal

func (c *JanusClient) ChangePrincipal(principal string) (ok bool, err error)

func (*JanusClient) ChangeUser

func (c *JanusClient) ChangeUser(username, password string) (ok bool, err error)

func (*JanusClient) Close

func (c *JanusClient) Close()

func (*JanusClient) Connect

func (c *JanusClient) Connect() (id int32, err error)

func (*JanusClient) Disconnect

func (c *JanusClient) Disconnect() (id int, err error)

func (*JanusClient) GetLogMessages

func (c *JanusClient) GetLogMessages(lastSeen uint32) (lines []string, newLastSeen int32, err error)

func (*JanusClient) GetVersionNo

func (c *JanusClient) GetVersionNo() (version string, err error)

func (*JanusClient) HelloMessage

func (c *JanusClient) HelloMessage() (id int, err error)

func (*JanusClient) Send

func (c *JanusClient) Send(m *Message) (r *Response, err error)

func (*JanusClient) UploadScript

func (c *JanusClient) UploadScript(category, name, source string, mode ScriptMode, encryption ScriptEncrypted) (ok bool, err error)

type Message

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

func CallClassOperation

func CallClassOperation(classAndOp string, parameters []string, parametersPDO []string) *Message

func ChangePrincipal

func ChangePrincipal(principalName string) *Message

func ChangeUser

func ChangeUser(username string, password Password) *Message

func Connect

func Connect() (m *Message)

func Disconnect

func Disconnect() (m *Message)

func ErrorMessages

func ErrorMessages(errorCode uint32) (m *Message)

func HelloMessage

func HelloMessage() *Message

func LogMessages

func LogMessages(lastSeen uint32) (m *Message)

func MessageFrom

func MessageFrom(data []byte) *Message

func NewMessage

func NewMessage() *Message

func RunScriptOnServer

func RunScriptOnServer(sourceCode string, scriptUrl string) *Message

func SetLanguage

func SetLanguage(language uint32) *Message

func (*Message) AddBoolean

func (m *Message) AddBoolean(parameterName ParameterName, value bool) *Message

func (*Message) AddByteSlice

func (m *Message) AddByteSlice(msg []byte) *Message

func (*Message) AddBytes

func (m *Message) AddBytes(msg ...byte) *Message

func (*Message) AddInt32

func (m *Message) AddInt32(parameterName ParameterName, value uint32) *Message

func (*Message) AddString

func (m *Message) AddString(parameterName ParameterName, msg string) *Message

func (*Message) AddStringList

func (m *Message) AddStringList(parameterName ParameterName, values []string)

func (*Message) Bytes

func (m *Message) Bytes() []byte

func (*Message) Len

func (m *Message) Len() int

type Operation

type Operation int32
const (
	OperationChangeUser         Operation = 27
	OperationDisconnectClient   Operation = 49
	OperationSetLanguage        Operation = 59
	OperationCallClassOperation Operation = 101
	OperationCOMOperation       Operation = 199
	OperationChangePrincipal    Operation = 203
	OperationSrvGui             Operation = 209
)

type ParameterName

type ParameterName int32
const (
	ParameterNameClientId     ParameterName = 1
	ParameterNameClassAndOp   ParameterName = 2
	ParameterNameValue        ParameterName = 4
	ParameterNameReturnValue  ParameterName = 5
	ParameterNameSomething    ParameterName = 8
	ParameterNameIndex        ParameterName = 13
	ParameterNameLanguage     ParameterName = 14 // COMMS_LANG int3232
	ParameterNameUser         ParameterName = 21 // COMMS_USER String
	ParameterNamePassword     ParameterName = 22 // COMMS_PASSWORD String
	ParameterNameLast         ParameterName = 25
	ParameterNameUserId       ParameterName = 40
	ParameterNameParameter    ParameterName = 48
	ParameterNameParameterPDO ParameterName = 49
	ParameterNameConversion   ParameterName = 51
	ParameterNamePrincipal    ParameterName = 80
	ParameterNameFilename     ParameterName = 87
	ParameterNameOpcode       ParameterName = 88
	ParameterNameFlag         ParameterName = 119
)

type Password

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

func NewPassword

func NewPassword(value string) Password

func (Password) Hash

func (h Password) Hash(salt string) string

func (Password) Janus

func (h Password) Janus() string

func (Password) String

func (h Password) String() string

type Response

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

func NewResponse

func NewResponse(content []byte) *Response

func (*Response) Bytes

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

func (*Response) GetBoolean

func (r *Response) GetBoolean(name ParameterName) (bool, error)

func (*Response) GetInt32

func (r *Response) GetInt32(name ParameterName) (int32, error)

func (*Response) GetString

func (r *Response) GetString(name ParameterName) (string, error)

func (*Response) GetStringList

func (r *Response) GetStringList(name ParameterName) ([]string, error)

func (*Response) IsSimple

func (r *Response) IsSimple() bool

func (*Response) Len

func (r *Response) Len() int

type ScriptEncrypted

type ScriptEncrypted string
const (
	ScriptEncryptedFalse      ScriptEncrypted = "false"
	ScriptEncryptedTrue       ScriptEncrypted = "true"
	ScriptEncryptedDecrypted  ScriptEncrypted = "decrypted"
	ScriptEncryptedForceFalse ScriptEncrypted = "forceFalse"
)

type ScriptMode

type ScriptMode string
const (
	ScriptModeModule  ScriptMode = "Module"
	ScriptModeClassic ScriptMode = "Classic"
)

type SrvGuiOperation

type SrvGuiOperation int32
const (
	SrvGuiOperationGetMessages SrvGuiOperation = 10
)

type Transport

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

func NewTransport

func NewTransport(conn net.Conn) *Transport

func (*Transport) Close

func (t *Transport) Close() error

func (*Transport) ErrorCode

func (t *Transport) ErrorCode(code uint32) (err error)

func (*Transport) Read

func (t *Transport) Read(b []byte) (n int, err error)

func (*Transport) Send

func (t *Transport) Send(msg *Message) (r *Response, err error)

func (*Transport) Write

func (t *Transport) Write(b []byte) (n int, err error)

type Type

type Type int32
const (
	TypeBoolean    Type = 2
	TypeInt32      Type = 3
	TypeDate       Type = 4
	TypeString     Type = 7
	TypeOID        Type = 9
	TypeInt32List  Type = 10
	TypeStringList Type = 11
	TypeOIDList    Type = 12
	TypeNullFlag   Type = 128
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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