mirror of https://gogs.blitter.com/RLabs/xs
				
				
				
			Tunnel rough work-in-progress; data sent (wrong length) and CSOTunClose handling needs work, but it's a start...
This commit is contained in:
		
							parent
							
								
									1e6da733a2
								
							
						
					
					
						commit
						632f24354b
					
				| 
						 | 
				
			
			@ -34,7 +34,7 @@ type KEXAlg uint8
 | 
			
		|||
// rather than remote end normal UNIX exit codes
 | 
			
		||||
const (
 | 
			
		||||
	CSENone = 1024 + iota
 | 
			
		||||
	CSEBadAuth     // Failed login password
 | 
			
		||||
	//CSEBadAuth     // Failed login password
 | 
			
		||||
	CSETruncCSO    // No CSOExitStatus in payload
 | 
			
		||||
	CSEStillOpen   // Channel closed unexpectedly
 | 
			
		||||
	CSEExecFail    // cmd.Start() (exec) failed
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +52,9 @@ const (
 | 
			
		|||
	CSOTermSize           // set term size (rows:cols)
 | 
			
		||||
	CSOTunReq             // client tunnel open request (dstport)
 | 
			
		||||
	CSOTunAck             // server tunnel open ack (tunport)
 | 
			
		||||
	CSOTunData            // packet contains [rport:data]
 | 
			
		||||
	CSOTunClose           // request to close connection (tunnel stays open)
 | 
			
		||||
	CSOTunRefused         // tunnel has died or could not be established to rport
 | 
			
		||||
	CSOExitStatus         // Remote cmd exit status
 | 
			
		||||
	CSOChaff              // Dummy packet, do not pass beyond decryption
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,30 +73,6 @@ type (
 | 
			
		|||
		szMax    uint // max size in bytes
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Tunnels
 | 
			
		||||
	// --
 | 
			
		||||
	// 1. client is given (lport, remhost, rport) by local user
 | 
			
		||||
	// 2. client sends [CSOTunReq:rport] to server
 | 
			
		||||
	// client=> [CSOTunReq:rport] =>remhost
 | 
			
		||||
	//    t := TunEndpoint{dataPort: lport, peer: remhost}
 | 
			
		||||
	//
 | 
			
		||||
	// remhost allocates dynamic (Tport)
 | 
			
		||||
	//    t := TunEndpoint{dataPort: rport, peer: client, tunPort: Tport}
 | 
			
		||||
	//
 | 
			
		||||
	// remhost spawns goroutine forwarding data between (Tport,rport)
 | 
			
		||||
	// client<= [CSOTunAck:Tport] <=remhost
 | 
			
		||||
	//    t.tunPort = Tport
 | 
			
		||||
	//
 | 
			
		||||
	// client spawns goroutine forwarding data between (lport,Tport)
 | 
			
		||||
	// --
 | 
			
		||||
 | 
			
		||||
	// TunEndpoint [securePort:peer:dataPort]
 | 
			
		||||
	TunEndpoint struct {
 | 
			
		||||
		TunPort  uint16
 | 
			
		||||
		Peer     string //net.Addr
 | 
			
		||||
		DataPort uint16
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Conn is a connection wrapping net.Conn with KEX & session state
 | 
			
		||||
	Conn struct {
 | 
			
		||||
		kex        KEXAlg      // KEX/KEM propsal (client -> server)
 | 
			
		||||
| 
						 | 
				
			
			@ -109,8 +85,7 @@ type (
 | 
			
		|||
		Cols       uint16
 | 
			
		||||
 | 
			
		||||
		chaff ChaffConfig
 | 
			
		||||
 | 
			
		||||
		tuns []TunEndpoint
 | 
			
		||||
		tuns  map[uint16]chan []byte
 | 
			
		||||
 | 
			
		||||
		closeStat *CSOType      // close status (CSOExitStatus)
 | 
			
		||||
		r         cipher.Stream //read cipherStream
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +102,7 @@ var (
 | 
			
		|||
 | 
			
		||||
// Return string (suitable as map key) for a tunnel endpoint
 | 
			
		||||
func (t *TunEndpoint) String() string {
 | 
			
		||||
	return fmt.Sprintf("[%d:%s:%d]", t.DataPort, t.Peer, t.TunPort)
 | 
			
		||||
	return fmt.Sprintf("[%d:%s:%d]", t.Lport, t.Peer, t.Rport)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func _initLogging(d bool, c string, f logger.Priority) {
 | 
			
		||||
| 
						 | 
				
			
			@ -261,12 +236,6 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (hc *Conn) applyConnExtensions(extensions ...string) {
 | 
			
		||||
	//fmt.Printf("CSENone:%d CSEBadAuth:%d CSETruncCSO:%d CSEStillOpen:%d CSEExecFail:%d CSEPtyExecFail:%d\n",
 | 
			
		||||
	//	CSENone, CSEBadAuth, CSETruncCSO, CSEStillOpen, CSEExecFail, CSEPtyExecFail)
 | 
			
		||||
 | 
			
		||||
	//fmt.Printf("CSONone:%d  CSOHmacInvalid:%d CSOTermSize:%d CSOExitStatus:%d CSOChaff:%d\n",
 | 
			
		||||
	//	CSONone, CSOHmacInvalid, CSOTermSize, CSOExitStatus, CSOChaff)
 | 
			
		||||
 | 
			
		||||
	for _, s := range extensions {
 | 
			
		||||
		switch s {
 | 
			
		||||
		case "C_AES_256":
 | 
			
		||||
| 
						 | 
				
			
			@ -821,16 +790,20 @@ func (hc Conn) Read(b []byte) (n int, err error) {
 | 
			
		|||
				}
 | 
			
		||||
				hc.Close()
 | 
			
		||||
			} else if ctrlStatOp == CSOTunReq {
 | 
			
		||||
				// This should ONLY be sent from client -> server!
 | 
			
		||||
				// TODO: Hmm. should this package (hkexnet) take a 'server'/'client' context
 | 
			
		||||
				// in order to know how to handle mis-uses?
 | 
			
		||||
				addrs, _ := net.InterfaceAddrs()
 | 
			
		||||
				t := TunEndpoint{Peer: addrs[0].String()}
 | 
			
		||||
				t.TunPort = binary.BigEndian.Uint16(payloadBytes)
 | 
			
		||||
				//fmt.Sscanf(string(payloadBytes), "%d", &t.tunPort)
 | 
			
		||||
				Log.Notice(fmt.Sprintf("[TODO: Client Tunnel Open Request - traffic for server %s, port %d]\n", t.Peer, t.TunPort))
 | 
			
		||||
			} else if ctrlStatOp == CSOTunAck {
 | 
			
		||||
				Log.Notice("[Server Tunnel Open Ack - TODO]\n")
 | 
			
		||||
				// Client wants a tunnel set up - args [lport:rport]
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes)
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				startServerTunnel(&hc, lport, rport)
 | 
			
		||||
			} else if ctrlStatOp == CSOTunData {
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes)
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				fmt.Printf("[Got CSOTunData: [lport %d:rport %d] data:%v\n", lport, rport, payloadBytes[4:])
 | 
			
		||||
				hc.tuns[rport] <- payloadBytes[4:]
 | 
			
		||||
			} else if ctrlStatOp == CSOTunClose {
 | 
			
		||||
				lport := binary.BigEndian.Uint16(payloadBytes)
 | 
			
		||||
				rport := binary.BigEndian.Uint16(payloadBytes[2:4])
 | 
			
		||||
				fmt.Printf("[Got CSOTunClose: [lport %d:rport %d]\n", lport, rport)
 | 
			
		||||
				hc.tuns[rport] = nil
 | 
			
		||||
			} else {
 | 
			
		||||
				hc.dBuf.Write(payloadBytes)
 | 
			
		||||
				//log.Printf("hc.dBuf: %s\n", hex.Dump(hc.dBuf.Bytes()))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -337,12 +337,27 @@ func rejectUserMsg() string {
 | 
			
		|||
	return "Begone, " + spinsult.GetSentence() + "\r\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func requestTunnel(c *hkexnet.Conn, dp uint16, p string /*net.Addr*/, tp uint16) (t hkexnet.TunEndpoint) {
 | 
			
		||||
	t = hkexnet.TunEndpoint{DataPort: dp, Peer: p, TunPort: tp}
 | 
			
		||||
// Transmit request to server for it to set up the remote end of a tunnel
 | 
			
		||||
//
 | 
			
		||||
// Server responds with [CSOTunAck:rport] or [CSOTunRefused:rport]
 | 
			
		||||
func requestTunnel(hc *hkexnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) (t hkexnet.TunEndpoint) {
 | 
			
		||||
	var bTmp bytes.Buffer
 | 
			
		||||
	binary.Write(&bTmp, binary.BigEndian, t.DataPort)
 | 
			
		||||
	c.WritePacket(bTmp.Bytes(), hkexnet.CSOTunReq)
 | 
			
		||||
	binary.Write(&bTmp, binary.BigEndian, lp)
 | 
			
		||||
	binary.Write(&bTmp, binary.BigEndian, rp)
 | 
			
		||||
	hc.WritePacket(bTmp.Bytes(), hkexnet.CSOTunReq)
 | 
			
		||||
 | 
			
		||||
	// Server should reply immediately with success (lport:rport) or
 | 
			
		||||
	// refusal (lport:0)
 | 
			
		||||
	var lportReply, rportReply uint16
 | 
			
		||||
	errL := binary.Read(hc, binary.BigEndian, &lportReply)
 | 
			
		||||
	errR := binary.Read(hc, binary.BigEndian, &rportReply)
 | 
			
		||||
	if errL == nil && errR == nil {
 | 
			
		||||
		fmt.Printf("Server established tunnel [%d:%d]\n", lportReply, rportReply)
 | 
			
		||||
		hkexnet.StartClientTunnel(hc, lp, rp)
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Println("FAILED reading remPort")
 | 
			
		||||
	}
 | 
			
		||||
	t = hkexnet.TunEndpoint{Lport: lportReply, Peer: p, Rport: rportReply}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -631,8 +646,6 @@ func main() {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if shellMode {
 | 
			
		||||
			// TODO: tunnel setup would be here or within doShellMode()
 | 
			
		||||
 | 
			
		||||
			// TESTING - tunnel
 | 
			
		||||
			remAddrs, _ := net.LookupHost(remoteHost)
 | 
			
		||||
			t := requestTunnel(&conn, 6001, remAddrs[0], 7001)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue