diff --git a/0x17_authorization_registration_service.go b/0x17_authorization_registration_service.go new file mode 100644 index 0000000..badc5ea --- /dev/null +++ b/0x17_authorization_registration_service.go @@ -0,0 +1,22 @@ +package main + +import ( + "context" + "fmt" +) + +var cipher = "hey wassup" + +type AuthorizationRegistrationService struct{} + +func (a *AuthorizationRegistrationService) HandleSNAC(ctx context.Context, snac *SNAC) { + // Request MD5 Auth Key + if snac.Header.Subtype == 0x06 { + fmt.Println("damn it's 0x06") + // cipherData := ByteString(cipher) // []byte + + // snac := NewSNAC(0x17, 0x07, cipherData) + + // resp := NewFLAP(2, snac) + } +} diff --git a/flap.go b/flap.go new file mode 100644 index 0000000..f6298d7 --- /dev/null +++ b/flap.go @@ -0,0 +1,70 @@ +package main + +import ( + "bytes" + "context" + "encoding" + "encoding/binary" + "fmt" +) + +var _ encoding.BinaryUnmarshaler = &FLAP{} +var _ encoding.BinaryMarshaler = &FLAP{} + +type FLAPHeader struct { + Channel uint8 + SequenceNumber uint16 + DataLength uint16 +} + +type FLAP struct { + Header FLAPHeader + Data []byte +} + +func NewFLAP(ctx context.Context, channel uint8, data []byte) *FLAP { + session := ctx.Value("session").(*Session) + session.SequenceNumber += 1 + + return &FLAP{ + Header: FLAPHeader{ + Channel: channel, + SequenceNumber: uint16(session.SequenceNumber), + DataLength: uint16(len(data)), + }, + Data: data, + } +} + +func (f *FLAP) UnmarshalBinary(data []byte) error { + buf := bytes.NewBuffer(data) + start, err := buf.ReadByte() + if err != nil { + return err + } + if start != 0x2a { + return fmt.Errorf("FLAP missing 0x2a header") + } + + if err = binary.Read(buf, binary.BigEndian, &f.Header); err != nil { + return err + } + + f.Data = buf.Bytes() + return nil +} + +func (f *FLAP) MarshalBinary() ([]byte, error) { + var buf bytes.Buffer + buf.WriteByte(0x2a) + binary.Write(&buf, binary.BigEndian, f.Header) + n, err := buf.Write(f.Data) + if n != int(f.Header.DataLength) { + return nil, fmt.Errorf("needed to write %d bytes to buffer but wrote %d", f.Header.DataLength, n) + } + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} diff --git a/main.go b/main.go index e1ac43c..4856b51 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,7 @@ package main import ( - "bytes" "context" - "encoding/binary" "fmt" "io" "log" @@ -19,21 +17,10 @@ const ( SRV_ADDRESS = SRV_HOST + ":" + SRV_PORT ) -type Session struct { - Conn net.Conn - GreetedClient bool -} +var services = make(map[uint16]Service) -func NewSession(conn net.Conn) *Session { - return &Session{ - Conn: conn, - GreetedClient: false, - } -} - -func (s *Session) Send(bytes []byte) { - fmt.Printf("-> %v\n%s\n\n", s.Conn.RemoteAddr(), prettyBytes(bytes)) - s.Conn.Write(bytes) +func init() { + services[0x17] = &AuthorizationRegistrationService{} } func main() { @@ -69,7 +56,9 @@ func main() { func handleTCPConnection(ctx context.Context, conn net.Conn) { defer (func() { - recover() + if r := recover(); r != nil { + log.Println("Error handling message: ", r.(error).Error()) + } conn.Close() log.Printf("Closed connection to %v", conn.RemoteAddr()) })() @@ -79,8 +68,9 @@ func handleTCPConnection(ctx context.Context, conn net.Conn) { session := ctx.Value("session").(*Session) if !session.GreetedClient { // send a hello - hello := []byte{0x2a, 1, 0, 0, 0, 4, 0, 0, 0, 1} - session.Send(hello) + hello := NewFLAP(ctx, 1, []byte{0, 0, 0, 1}) + err := session.Send(hello) + panicIfError(err) session.GreetedClient = true } @@ -100,26 +90,18 @@ func handleTCPConnection(ctx context.Context, conn net.Conn) { } func handleMessage(ctx context.Context, buf []byte) { - messageBuf := bytes.NewBuffer(buf) + flap := &FLAP{} + flap.UnmarshalBinary(buf) - start, err := messageBuf.ReadByte() - panicIfError(err) - if start != 0x2a { - log.Println("FLAP message missing leading 0x2a") - return + if flap.Header.Channel == 1 { + + } else if flap.Header.Channel == 2 { + snac := &SNAC{} + err := snac.UnmarshalBinary(flap.Data) + panicIfError(err) + + if service, ok := services[snac.Header.Family]; ok { + service.HandleSNAC(ctx, snac) + } } - - type FLAP struct { - Channel uint8 - SequenceNumber uint16 - DataLength uint16 - } - - flap := FLAP{} - panicIfError(binary.Read(messageBuf, binary.BigEndian, &flap)) - - // Start parsing FLAP header - log.Println("Message for channel: ", flap.Channel) - log.Println("Datagram Sequence Number: ", flap.SequenceNumber) - log.Println("Data Length: ", flap.DataLength) } diff --git a/service.go b/service.go new file mode 100644 index 0000000..d7de403 --- /dev/null +++ b/service.go @@ -0,0 +1,9 @@ +package main + +import ( + "context" +) + +type Service interface { + HandleSNAC(context.Context, *SNAC) +} diff --git a/session.go b/session.go new file mode 100644 index 0000000..7d82128 --- /dev/null +++ b/session.go @@ -0,0 +1,32 @@ +package main + +import ( + "encoding" + "fmt" + "net" +) + +type Session struct { + Conn net.Conn + SequenceNumber uint16 + GreetedClient bool +} + +func NewSession(conn net.Conn) *Session { + return &Session{ + Conn: conn, + SequenceNumber: 0, + GreetedClient: false, + } +} + +func (s *Session) Send(m encoding.BinaryMarshaler) error { + bytes, err := m.MarshalBinary() + if err != nil { + return err + } + + fmt.Printf("-> %v\n%s\n\n", s.Conn.RemoteAddr(), prettyBytes(bytes)) + _, err = s.Conn.Write(bytes) + return err +} diff --git a/snac.go b/snac.go new file mode 100644 index 0000000..666727f --- /dev/null +++ b/snac.go @@ -0,0 +1,58 @@ +package main + +import ( + "bytes" + "encoding/binary" + "fmt" +) + +type SNACHeader struct { + Family uint16 + Subtype uint16 + Flags uint16 + RequestID uint16 +} + +type SNAC struct { + Header SNACHeader + Data []byte +} + +func NewSNAC(family uint16, subtype uint16, data []byte) *SNAC { + return &SNAC{ + Header: SNACHeader{ + Family: family, + Subtype: subtype, + Flags: 0, + RequestID: 0, + }, + Data: data, + } +} + +func (s *SNAC) MarshalBinary() ([]byte, error) { + var buf bytes.Buffer + + binary.Write(&buf, binary.BigEndian, s.Header) + n, err := buf.Write(s.Data) + if n != len(s.Data) { + return nil, fmt.Errorf("needed to write %d bytes to buffer but wrote %d", len(s.Data), n) + } + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func (s *SNAC) UnmarshalBinary(data []byte) error { + buf := bytes.NewBuffer(data) + + if err := binary.Read(buf, binary.BigEndian, &s.Header); s != nil { + return err + } + + s.Data = buf.Bytes() + + return nil +}