Skip to content

Commit

Permalink
pre-release version 2 of the client major changes:
Browse files Browse the repository at this point in the history
1- update client version to:
2- update ttc version to: 9
3- use 4 byte packet length instead of 2 bytes
4- use advanced negotiation
5- define NCHARSET in the data type negotiation and
6- use big clear chunks
7- use more verifier type in authentication object
8- receive session properties after authentication without calling getNLSData()
  • Loading branch information
sijms committed Mar 7, 2021
1 parent 7dda604 commit fbc3c8c
Show file tree
Hide file tree
Showing 27 changed files with 2,450 additions and 461 deletions.
142 changes: 142 additions & 0 deletions advanced_nego/advanced_nego.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package advanced_nego

import (
"errors"
"github.com/sijms/go-ora/network"
)

type AdvNego struct {
serviceList []AdvNegoService
}

func NewAdvNego(connOption *network.ConnectionOption) (*AdvNego, error) {
output := &AdvNego{
serviceList: make([]AdvNegoService, 5),
}
var err error
output.serviceList[1], err = NewAuthService(connOption)
if err != nil {
return nil, err
}
output.serviceList[2], err = NewEncryptService(connOption)
if err != nil {
return nil, err
}
output.serviceList[3], err = NewDataIntegrityService(connOption)
if err != nil {
return nil, err
}
output.serviceList[4], err = NewSupervisorService()
if err != nil {
return nil, err
}
return output, nil
}
func (nego *AdvNego) readHeader(session *network.Session) ([]int, error) {
num, err := session.GetInt(4, false, true)
if err != nil {
return nil, err
}
if num != 0xDEADBEEF {
return nil, errors.New("advanced negotiation error: during receive header")
}
output := make([]int, 4)
output[0], err = session.GetInt(2, false, true)
if err != nil {
return nil, err
}
output[1], err = session.GetInt(4, false, true)
if err != nil {
return nil, err
}
output[2], err = session.GetInt(2, false, true)
if err != nil {
return nil, err
}
output[3], err = session.GetInt(1, false, true)
return output, err
}
func (nego *AdvNego) readServiceHeader(session *network.Session) ([]int, error) {
output := make([]int, 3)
var err error
output[0], err = session.GetInt(2, false, true)
if err != nil {
return nil, err
}
output[1], err = session.GetInt(2, false, true)
if err != nil {
return nil, err
}
output[2], err = session.GetInt(4, false, true)
return output, err
}
func (nego *AdvNego) Read(session *network.Session) error {
header, err := nego.readHeader(session)
if err != nil {
return err
}
for i := 0; i < header[2]; i++ {
serviceHeader, err := nego.readServiceHeader(session)
if err != nil {
return err
}
if serviceHeader[2] != 0 {
return errors.New("advanced negotiation error: during receive service header")
}
err = nego.serviceList[serviceHeader[0]].readServiceData(session, serviceHeader[1])
if err != nil {
return err
}
err = nego.serviceList[serviceHeader[0]].validateResponse()
if err != nil {
return err
}
}
for i := 1; i < 5; i++ {
err = nego.serviceList[i].activateAlgorithm()
if err != nil {
return err
}
}
if authServ, ok := nego.serviceList[1].(*authService); ok {
if authServ.active {
errors.New("advanced negotiation: advanced authentication still not supported")
if authServ.serviceName == "KERBEROS5" {

} else if authServ.serviceName == "NTS" {

}
}
}
return nil
}
func (nego *AdvNego) Write(session *network.Session) error {
session.ResetBuffer()
size := 0
for i := 1; i < 5; i++ {
size = size + 8 + nego.serviceList[i].getServiceDataLength()
}
size += 13
session.PutInt(0xDEADBEEF, 4, true, false)
session.PutInt(size, 2, true, false)
session.PutInt(nego.serviceList[1].getVersion(), 4, true, false)
session.PutInt(4, 2, true, false)
session.PutBytes(0)
err := nego.serviceList[4].writeServiceData(session)
if err != nil {
return err
}
err = nego.serviceList[1].writeServiceData(session)
if err != nil {
return err
}
err = nego.serviceList[2].writeServiceData(session)
if err != nil {
return err
}
err = nego.serviceList[3].writeServiceData(session)
if err != nil {
return err
}
return session.Write()
}
157 changes: 157 additions & 0 deletions advanced_nego/auth_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package advanced_nego

import (
"errors"
"github.com/sijms/go-ora/network"
"runtime"
)

type authService struct {
defaultService
status int
serviceName string
active bool
}

func NewAuthService(connOption *network.ConnectionOption) (*authService, error) {
output := &authService{
defaultService: defaultService{
serviceType: 1,
level: -1,
version: 0xB200200,
},
status: 0xFCFF,
}
//var avaAuth []string
if runtime.GOOS == "windows" {
output.availableServiceNames = []string{"", "NTS", "KERBEROS5", "TCPS"}
output.availableServiceIDs = []int{0, 1, 1, 2}
} else {
output.availableServiceNames = []string{"TCPS"}
output.availableServiceIDs = []int{2}
}
str := ""
if connOption != nil {
snConfig := connOption.SNOConfig
if snConfig != nil {
var exists bool
str, exists = snConfig["sqlnet.authentication_services"]
if !exists {
str = ""
}
}
}
//level := conops.Encryption != null ? conops.Encryption : snoConfig[];
err := output.buildServiceList(str, false, false)
//output.selectedServ, err = output.validate(strings.Split(str,","), true)
if err != nil {
return nil, err
}
return output, nil
/* user list is found in the dictionary
sessCtx.m_conops.SNOConfig["sqlnet.authentication_services"]
*/
/* you need to confirm that every item in user list found in avaAuth list
then for each item in userList you need to get index of it in the avaAuth
return output*/
}

func (serv *authService) writeServiceData(session *network.Session) error {
serv.writeHeader(session, 3+(len(serv.selectedIndices)*2))
err := serv.writeVersion(session)
if err != nil {
return err
}
err = serv.writePacketHeader(session, 2, 3)
if err != nil {
return err
}
session.PutInt(0xE0E1, 2, true, false)
err = serv.writePacketHeader(session, 2, 6)
if err != nil {
return err
}
session.PutInt(serv.status, 2, true, false)
for i := 0; i < len(serv.selectedIndices); i++ {
index := serv.selectedIndices[i]
session.PutBytes(uint8(serv.availableServiceIDs[index]))
session.PutBytes([]byte(serv.availableServiceNames[index])...)
}
return nil
}

func (serv *authService) readServiceData(session *network.Session, subPacketNum int) error {
// read version
var err error
serv.version, err = serv.readVersion(session)
if err != nil {
return err
}
// read status
_, err = serv.readPacketHeader(session, 6)
if err != nil {
return err
}
status, err := session.GetInt(2, false, true)
if err != nil {
return err
}
if status == 0xFAFF && subPacketNum > 2 {
// get 1 byte with header
_, err = serv.readPacketHeader(session, 2)
if err != nil {
return err
}
_, err = session.GetByte()
if err != nil {
return err
}
stringLen, err := serv.readPacketHeader(session, 0)
if err != nil {
return err
}
serviceNameBytes, err := session.GetBytes(stringLen)
if err != nil {
return err
}
serv.serviceName = string(serviceNameBytes)
if subPacketNum > 4 {
_, err = serv.readVersion(session)
if err != nil {
return err
}
_, err = serv.readPacketHeader(session, 4)
if err != nil {
return err
}
_, err = session.GetInt(4, false, true)
if err != nil {
return err
}
_, err = serv.readPacketHeader(session, 4)
if err != nil {
return err
}
_, err = session.GetInt(4, false, true)
if err != nil {
return err
}
}
serv.active = true
} else {
if status != 0xFBFF {
return errors.New("advanced negotiation error: reading authentication service")
}
serv.active = false
}
return nil
}

func (serv *authService) getServiceDataLength() int {
size := 20
for i := 0; i < len(serv.selectedIndices); i++ {
index := serv.selectedIndices[i]
size = size + 5 + (4 + len(serv.availableServiceNames[index]))
}
return size
}
Loading

0 comments on commit fbc3c8c

Please sign in to comment.