Fix: don't accept unencrypted messages

This commit is contained in:
robert
2026-02-26 17:09:01 +00:00
parent 85929ced9b
commit dc92793db9
2 changed files with 56 additions and 42 deletions

View File

@@ -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) {

View File

@@ -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, "")