Fix: don't accept unencrypted messages
This commit is contained in:
92
client.go
92
client.go
@@ -185,53 +185,65 @@ func (c *Client) read_loop(ctx context.Context, pending []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) handle_incoming_text(s string) {
|
func (c *Client) handle_incoming_text(s string) {
|
||||||
if len(s) > 0 && s[0] == '/' {
|
if len(s) > 0 && s[0] == '/' {
|
||||||
// Ignore unknown commands after handshake for now.
|
return
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var in incoming_frame
|
var in incoming_frame
|
||||||
if err := json.Unmarshal([]byte(s), &in); err != nil {
|
if err := json.Unmarshal([]byte(s), &in); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
if !c.ready {
|
if !c.ready {
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_key := c.state.SharedKey
|
shared_key := c.state.SharedKey
|
||||||
session_id_bytes := c.state.SessionIdBytes
|
session_id_bytes := c.state.SessionIdBytes
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
|
||||||
content := in.Content
|
// Enforce encryption after handshake.
|
||||||
|
if !in.IsEncrypted {
|
||||||
|
c.emit(Event{
|
||||||
|
Kind: EventError,
|
||||||
|
Err: fmt.Errorf("received unencrypted message after handshake"),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if in.IsEncrypted {
|
plain, err := DecryptAESGCM(
|
||||||
plain, err := DecryptAESGCM(shared_key, session_id_bytes, in.Content, in.Salt, in.SeqNum, in.IsResponse)
|
shared_key,
|
||||||
if err != nil {
|
session_id_bytes,
|
||||||
c.emit(Event{Kind: EventError, Err: err})
|
in.Content,
|
||||||
return
|
in.Salt,
|
||||||
}
|
in.SeqNum,
|
||||||
content = string(plain)
|
in.IsResponse,
|
||||||
}
|
)
|
||||||
|
if err != nil {
|
||||||
|
c.emit(Event{Kind: EventError, Err: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.mu.Lock()
|
content := string(plain)
|
||||||
if in.SeqNum > c.state.SeqInMax {
|
|
||||||
c.state.SeqInMax = in.SeqNum
|
|
||||||
}
|
|
||||||
c.mu.Unlock()
|
|
||||||
|
|
||||||
c.emit(Event{
|
c.mu.Lock()
|
||||||
Kind: EventMessage,
|
if in.SeqNum > c.state.SeqInMax {
|
||||||
Message: Message{
|
c.state.SeqInMax = in.SeqNum
|
||||||
Content: content,
|
}
|
||||||
Metadata: in.Metadata,
|
c.mu.Unlock()
|
||||||
SeqNum: in.SeqNum,
|
|
||||||
IsResponse: in.IsResponse,
|
c.emit(Event{
|
||||||
CreatedAt: in.CreatedAt,
|
Kind: EventMessage,
|
||||||
},
|
Message: Message{
|
||||||
})
|
Content: content,
|
||||||
|
Metadata: in.Metadata,
|
||||||
|
SeqNum: in.SeqNum,
|
||||||
|
IsResponse: in.IsResponse,
|
||||||
|
CreatedAt: in.CreatedAt,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) emit(ev Event) {
|
func (c *Client) emit(ev Event) {
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ var _ = Describe("Client", func() {
|
|||||||
written := <-conn.write_ch
|
written := <-conn.write_ch
|
||||||
Expect(written).To(HavePrefix("/create:"))
|
Expect(written).To(HavePrefix("/create:"))
|
||||||
|
|
||||||
|
// First complete handshake
|
||||||
|
conn.read_ch <- "/session:" + session_id + ":" + server_pub_b64 + ":" + salt_b64 + ":12:34"
|
||||||
|
|
||||||
|
// Then send encrypted history (now processed normally)
|
||||||
history_enc, err := sdk.EncryptAESGCM(shared_key, session_id_bytes, []byte("hist"), 10, false)
|
history_enc, err := sdk.EncryptAESGCM(shared_key, session_id_bytes, []byte("hist"), 10, false)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
@@ -68,8 +72,6 @@ var _ = Describe("Client", func() {
|
|||||||
"created_at": int64(1),
|
"created_at": int64(1),
|
||||||
})
|
})
|
||||||
conn.read_ch <- string(history_json)
|
conn.read_ch <- string(history_json)
|
||||||
|
|
||||||
conn.read_ch <- "/session:" + session_id + ":" + server_pub_b64 + ":" + salt_b64 + ":12:34"
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = client.Connect(ctx, "")
|
err = client.Connect(ctx, "")
|
||||||
|
|||||||
Reference in New Issue
Block a user