Ver Fonte

Fixed a whole lot, but can only act as an SSID checker

Viktor Grahn há 7 anos atrás
pai
commit
4169972b1f
3 ficheiros alterados com 266 adições e 240 exclusões
  1. 17 15
      main.go
  2. 221 211
      oftp.go
  3. 28 14
      typedef.go

+ 17 - 15
main.go

@@ -1,27 +1,29 @@
 package main
 
 import (
-  "os"
-  "fmt"
+	"fmt"
+	"os"
 )
 
 func main() {
-  if len(os.Args) != 2 {
-    fmt.Println("Usage:   oftpTester <profile-config>\nExample: oftpTester encodeChinet.json")
-    os.Exit(1)
-  }
+	if len(os.Args) != 2 {
+		fmt.Fprintln(os.Stderr, "Usage:   oftpTester <profile-config>\nExample: oftpTester encodeChinet.json")
+		os.Exit(1)
+	}
 
-  var oftp Oftp
+	var oftp Oftp
 
-  err := oftp.New(os.Args[1])
-  if err != nil {
-    fmt.Println(err)
-    os.Exit(2)
-  }
+	err := oftp.New(os.Args[1])
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(2)
+	}
 
-  fmt.Printf("%+v\n", oftp)
+	err = oftp.Call()
 
-  err = oftp.Call()
-  fmt.Println(err)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(3)
+	}
 
 }

+ 221 - 211
oftp.go

@@ -1,243 +1,253 @@
 package main
 
 import (
-  "os"
-  "time"
-  "encoding/json"
-  "encoding/binary"
-  "net"
-  "fmt"
-  "errors"
+	"encoding/binary"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"net"
+	"os"
+	"strconv"
+	"time"
 )
 
 func (o *Oftp) New(filename string) error {
-  // Set default values
-  newOftp := Oftp{
-    LocalCode: "LOCALCODE",
-    LocalPassword: "LOCALPWD",
-    PartnerCode: "1234567890CODE",
-    PartnerPassword: "SUPERSECRET",
-    OftpLevel: 4,
-    OftpBuffer: 512,
-    OftpDuplex: "S",
-    OftpCompression: "N",
-    OftpRestart: "N",
-    OftpCredit: 7,
-    OftpAuthentication: "N",
-    NetworkHost: "localhost",
-    NetworkPort: 3305,
-    NetworkTLS: false,
-  }
-
-  f, err := os.Open(filename)
-  if err != nil {
-    return err
-  }
-  defer f.Close()
-
-  d := json.NewDecoder(f)
-
-  if err := d.Decode(&newOftp); err != nil {
-    return err
-  }
-
-  *o = newOftp
-
-  return nil
+	// Set default values
+	newOftp := Oftp{
+		LocalCode:          "LOCALCODE",
+		LocalPassword:      "LOCALPWD",
+		PartnerCode:        "1234567890CODE",
+		PartnerPassword:    "SUPERSECRET",
+		OftpLevel:          4,
+		OftpBuffer:         512,
+		OftpDuplex:         "S",
+		OftpCompression:    "N",
+		OftpRestart:        "N",
+		OftpCredit:         7,
+		OftpAuthentication: "N",
+		NetworkHost:        "localhost",
+		NetworkPort:        3305,
+		NetworkTimeout:     10,
+		NetworkTLS:         false,
+	}
+
+	f, err := os.Open(filename)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	d := json.NewDecoder(f)
+
+	if err := d.Decode(&newOftp); err != nil {
+		return err
+	}
+
+	*o = newOftp
+
+	return nil
 }
 
 func (o Oftp) Call() error {
-  // 1. Open connection
-  // 2. Wait for SSRM
-  // 3. Send SSID
-  // 4. Wait for SSID
-  // 5. Validate SSID
-  // 6. Send ESID
-
-  // 1. Open connection
-  addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", o.NetworkHost, o.NetworkPort))
-  if err != nil {
-    return err
-  }
-
-  conn, err := net.DialTCP("tcp", nil, addr)
-  if err != nil {
-    return err
-  }
-  defer conn.Close()
-
-  fmt.Printf("Connected to %s\n", addr.String())
-
-  // 2. Wait for SSRM
-  headerBuf := make([]byte, 4)
-  dataBuf := make([]byte, o.OftpBuffer)
-
-  // Read STH (header)
-  readCnt, err := conn.Read(headerBuf)
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  length, err := parseSTH(headerBuf[:4])
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  fmt.Printf("STH says STB is %d long\n", length)
-
-  // Read OFTP command
-  readCnt, err = conn.Read(dataBuf)
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  fmt.Printf("Read %d, should be %d\n", readCnt, length - 4)
-
-  if string(dataBuf[:readCnt]) != "IODETTE FTP READY \r" && string(dataBuf[:readCnt]) != "IODETTE FTP READY \n"{
-    conn.Close()
-    return errors.New(fmt.Sprintf("Expected SSRM (%x), got %x", "IODETTE FTP READY \r", dataBuf[:readCnt]))
-  }
-
-  // 3. Send SSID
-  fmt.Println(string(o.LocalSSID()))
-  writtenCnt, err := conn.Write(o.LocalSSID())
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  fmt.Printf("Write %d bytes to %s\n", writtenCnt, addr.String())
-
-  // 4. Wait for SSID
-  // Read STH (header)
-  readCnt, err = conn.Read(headerBuf)
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  length, err = parseSTH(headerBuf[:4])
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  fmt.Printf("STH says STB is %d long\n", length)
-
-  // Read OFTP command
-  readCnt, err = conn.Read(dataBuf)
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  fmt.Printf("Read %d, should be %d\n", readCnt, length - 4)
-
-  // 5. Validate SSID
-  ESIDCode := o.ValidateSSID(dataBuf[:readCnt]);
-  if ESIDCode < 0 {
-    // If ESID is received, disconnect
-    conn.Close()
-    return err
-  }
-
-  // 6. Send ESID
-  fmt.Println(string(o.ESID(ESIDCode)))
-  writtenCnt, err = conn.Write(o.ESID(ESIDCode))
-  if err != nil {
-    conn.Close()
-    return err
-  }
-
-  fmt.Printf("Write %d bytes to %s\n", writtenCnt, addr.String())
-
-  // Wait for partner to disconnect
-  conn.SetReadDeadline(time.Now().Add(10 * time.Second))
-  conn.Read(dataBuf)
-  conn.Close()
-  return nil
+	// 1. Open connection
+	// 2. Wait for SSRM
+	// 3. Send SSID
+	// 4. Wait for SSID
+	// 5. Validate SSID
+	// 6. Send ESID
+
+	// 1. Open connection
+
+	conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", o.NetworkHost, o.NetworkPort), time.Duration(o.NetworkTimeout)*time.Second)
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+
+	fmt.Printf("Connected to %s:%d\n", o.NetworkHost, o.NetworkPort)
+
+	// 2. Wait for SSRM
+	headerBuf := make([]byte, 4)
+	dataBuf := make([]byte, o.OftpBuffer)
+
+	// Read STH (header)
+	readCnt, err := conn.Read(headerBuf)
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	_, err = parseSTH(headerBuf[:4])
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	// Read OFTP command
+	readCnt, err = conn.Read(dataBuf)
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	if string(dataBuf[:readCnt]) != "IODETTE FTP READY \r" && string(dataBuf[:readCnt]) != "IODETTE FTP READY \n" {
+		conn.Close()
+		return errors.New(fmt.Sprintf("Expected SSRM (%x), got %x", "IODETTE FTP READY \r", dataBuf[:readCnt]))
+	}
+
+	fmt.Printf("Received SSRM (%d)\n", readCnt)
+
+	// 3. Send SSID
+	writtenCnt, err := conn.Write(o.LocalSSID())
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	fmt.Printf("Sent SSID (%d)\n", writtenCnt)
+
+	// 4. Wait for SSID
+	// Read STH (header)
+	readCnt, err = conn.Read(headerBuf)
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	_, err = parseSTH(headerBuf[:4])
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	// Read OFTP command
+	readCnt, err = conn.Read(dataBuf)
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	// 5. Validate SSID
+	ESIDCode := o.ValidateSSID(dataBuf[:readCnt])
+	if ESIDCode < 0 {
+		fmt.Println(ESIDCode)
+		var err error
+		if ESIDCode > -100 {
+			// ESID error, disconnect
+			err = errors.New(fmt.Sprintf("Received negative ESID with reason code %d", ESIDCode*-1))
+		} else {
+			err = errors.New("Bad non-ESID reply to SSID")
+		}
+		conn.Close()
+		return err
+	}
+
+	fmt.Printf("Received SSID (%d)\n", readCnt)
+
+	// 6. Send ESID
+	writtenCnt, err = conn.Write(o.ESID(ESIDCode))
+	if err != nil {
+		conn.Close()
+		return err
+	}
+
+	fmt.Printf("Sent ESID (%d) with code %d\n", writtenCnt, ESIDCode)
+
+	// Wait for partner to disconnect
+	conn.SetReadDeadline(time.Now().Add(10 * time.Second))
+	conn.Read(dataBuf)
+	conn.Close()
+
+	fmt.Println("Disconnected")
+
+	if ESIDCode != 0 {
+		return errors.New(fmt.Sprintf("Ended session with ESID reason code %d", ESIDCode))
+	}
+
+	return nil
 }
 
 func (o Oftp) LocalSSID() []byte {
-  dataBuf := [61]byte{}
-  copy(dataBuf[0:1], "X")
-  copy(dataBuf[1:2], fmt.Sprintf("%d", o.OftpLevel))
-  copy(dataBuf[2:27], o.LocalCode)
-  copy(dataBuf[27:35], o.LocalPassword)
-  copy(dataBuf[35:40], fmt.Sprintf("%05d", o.OftpBuffer))
-  copy(dataBuf[40:41], o.OftpDuplex)
-  copy(dataBuf[41:42], o.OftpCompression)
-  copy(dataBuf[42:43], o.OftpRestart)
-  copy(dataBuf[43:44], "N")
-  copy(dataBuf[44:47], fmt.Sprintf("%03d", o.OftpCredit))
-  copy(dataBuf[47:48], o.OftpAuthentication)
-  copy(dataBuf[60:61], "\r")
-
-  sth := buildSTH(len(dataBuf))
-
-  stb := []byte{}
-
-  stb = append(stb, sth...)
-  stb = append(stb, dataBuf[:]...)
-
-  return stb
+	dataBuf := [61]byte{}
+	copy(dataBuf[0:1], "X")
+	copy(dataBuf[1:2], fmt.Sprintf("%d", o.OftpLevel))
+	copy(dataBuf[2:27], o.LocalCode)
+	copy(dataBuf[27:35], o.LocalPassword)
+	copy(dataBuf[35:40], fmt.Sprintf("%05d", o.OftpBuffer))
+	copy(dataBuf[40:41], o.OftpDuplex)
+	copy(dataBuf[41:42], o.OftpCompression)
+	copy(dataBuf[42:43], o.OftpRestart)
+	copy(dataBuf[43:44], "N")
+	copy(dataBuf[44:47], fmt.Sprintf("%03d", o.OftpCredit))
+	copy(dataBuf[47:48], o.OftpAuthentication)
+	copy(dataBuf[60:61], "\r")
+
+	sth := buildSTH(len(dataBuf))
+
+	stb := []byte{}
+
+	stb = append(stb, sth...)
+	stb = append(stb, dataBuf[:]...)
+
+	return stb
 }
 
 func (o Oftp) ESID(code int) []byte {
-  dataBuf := [7]byte{}
-  copy(dataBuf[0:1], "F")
-  copy(dataBuf[1:3], fmt.Sprintf("%02d", code))
-  copy(dataBuf[3:6], fmt.Sprintf("%03d", 0))
-  copy(dataBuf[6:7], "\r")
+	dataBuf := [7]byte{}
+	copy(dataBuf[0:1], "F")
+	copy(dataBuf[1:3], fmt.Sprintf("%02d", code))
+	copy(dataBuf[3:6], fmt.Sprintf("%03d", 0))
+	copy(dataBuf[6:7], "\r")
 
-  sth := buildSTH(len(dataBuf))
-  stb := []byte{}
+	sth := buildSTH(len(dataBuf))
+	stb := []byte{}
 
-  stb = append(stb, sth...)
-  stb = append(stb, dataBuf[:]...)
+	stb = append(stb, sth...)
+	stb = append(stb, dataBuf[:]...)
 
-  return stb
+	return stb
 }
 
 func (o Oftp) ValidateSSID(SSIDBytes []byte) int {
-  // Validate cmd, code and password only
-  fmt.Println(string(SSIDBytes))
-  cmdByte := string(SSIDBytes[0:1])
-  if cmdByte != "X" {
-    return -1
-  }
-
-  codeBytes := string(SSIDBytes[2:27])
-  if codeBytes != fmt.Sprintf("%-25s", o.PartnerCode) {
-    return 3
-  }
-
-  passwordBytes := string(SSIDBytes[27:35])
-  if passwordBytes != fmt.Sprintf("%-8s", o.PartnerPassword) {
-    return 4
-  }
-
-  return 0
+	// Validate cmd, code and password only
+	cmdByte := string(SSIDBytes[0:1])
+	if cmdByte == "F" {
+		ESIDCodeStr := string(SSIDBytes[1:3])
+		ESIDCodeInt, _ := strconv.Atoi(ESIDCodeStr)
+		return -1 * ESIDCodeInt
+	}
+	if cmdByte != "X" {
+		return -100
+	}
+
+	codeBytes := string(SSIDBytes[2:27])
+	if codeBytes != fmt.Sprintf("%-25s", o.PartnerCode) {
+		return 3
+	}
+
+	passwordBytes := string(SSIDBytes[27:35])
+	if passwordBytes != fmt.Sprintf("%-8s", o.PartnerPassword) {
+		return 4
+	}
+
+	return 0
 
 }
 
 func parseSTH(sth []byte) (int32, error) {
-  sth[0] = 0
-  length := binary.BigEndian.Uint32(sth)
-  return int32(length), nil
+	sth[0] = 0
+	length := binary.BigEndian.Uint32(sth)
+	return int32(length), nil
 }
 
 func buildSTH(length int) []byte {
-  sth := make([]byte, 4)
-  sth[0] = 16
+	sth := make([]byte, 4)
+	sth[0] = 16
 
-  lengthBytes := make([]byte, 4)
-  binary.BigEndian.PutUint32(lengthBytes, uint32(length + 4))
-  copy(sth[1:4], lengthBytes[1:4])
+	lengthBytes := make([]byte, 4)
+	binary.BigEndian.PutUint32(lengthBytes, uint32(length+4))
+	copy(sth[1:4], lengthBytes[1:4])
 
-  return sth
+	return sth
 
 }

+ 28 - 14
typedef.go

@@ -1,18 +1,32 @@
 package main
 
 type Oftp struct {
-  LocalCode string `json:"LocalCode"`
-  LocalPassword string `json:"LocalPassword"`
-  PartnerCode string `json:"PartnerCode"`
-  PartnerPassword string `json:"PartnerPassword"`
-  OftpLevel int `json:"OftpLevel"`
-  OftpBuffer int `json:"OftpBuffer"`
-  OftpDuplex string `json:"OftpDuplex"`
-  OftpCompression string `json:"OftpCompression"`
-  OftpRestart string `json:"OftpRestart"`
-  OftpCredit int `json:"OftpCredit"`
-  OftpAuthentication string `json:"OftpAuthentication"`
-  NetworkHost string `json:"NetworkHost"`
-  NetworkPort int `json:"NetworkPort"`
-  NetworkTLS bool `json:"NetworkTLS"`
+	LocalCode          string `json:"LocalCode"`
+	LocalPassword      string `json:"LocalPassword"`
+	PartnerCode        string `json:"PartnerCode"`
+	PartnerPassword    string `json:"PartnerPassword"`
+	OftpLevel          int    `json:"OftpLevel"`
+	OftpBuffer         int    `json:"OftpBuffer"`
+	OftpDuplex         string `json:"OftpDuplex"`
+	OftpCompression    string `json:"OftpCompression"`
+	OftpRestart        string `json:"OftpRestart"`
+	OftpCredit         int    `json:"OftpCredit"`
+	OftpAuthentication string `json:"OftpAuthentication"`
+	NetworkHost        string `json:"NetworkHost"`
+	NetworkPort        int    `json:"NetworkPort"`
+	NetworkTimeout     int    `json:"NetworkTimeout"`
+	NetworkTLS         bool   `json:"NetworkTLS"`
+}
+
+type OftpError struct {
+	err  string
+	code string
+}
+
+func (o OftpError) Error() string {
+	return o.err
+}
+
+func (o OftpError) Code() string {
+	return o.code
 }