Preserve empty device content types with an explicit context flag
This commit is contained in:
1 parent
4dc5e1b11c
commit
a1dd1fda75
3 files changed
+14
-14
No files matched your search
+3
-3
@@ -430,7 +430,7 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t
|
||||
u_free(enc); return -1;
|
||||
}
|
||||
size_t body_len = DM_MSG_FIXED_HDR + ct_len + 2 + enc_len + (media ? DM_MEDIA_DESC_SIZE : 0) + DM_MSG_SIG_SIZE;
|
||||
if (context_size) body_len += context_size + 1;
|
||||
body_len += context_size;
|
||||
uint8_t* body = u_malloc(body_len);
|
||||
if (!body) { u_free(enc); return -1; }
|
||||
size_t off = 0;
|
||||
@@ -438,11 +438,11 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t
|
||||
memcpy(body + off, &seq, 8); off += 8;
|
||||
memcpy(body + off, &ts, 8); off += 8;
|
||||
memcpy(body + off, &author, 8); off += 8;
|
||||
if (context_size) { body[off++] = 0; memcpy(body + off, context, context_size); off += context_size; }
|
||||
body[off++] = ct_len;
|
||||
memcpy(body + off, ct, ct_len); off += ct_len;
|
||||
uint16_t el = (uint16_t)enc_len;
|
||||
uint16_t el = (uint16_t)(enc_len | (context_size ? DM_CONTEXT_FLAG : 0));
|
||||
memcpy(body + off, &el, 2); off += 2;
|
||||
if (context_size) { memcpy(body + off, context, context_size); off += context_size; }
|
||||
memcpy(body + off, enc, enc_len); off += enc_len;
|
||||
if (media) { memcpy(body + off, media, DM_MEDIA_DESC_SIZE); off += DM_MEDIA_DESC_SIZE; }
|
||||
/* подпись по всем полям до sig */
|
||||
|
||||
@@ -23,8 +23,12 @@ int dm_message_parse(const uint8_t* body, size_t available, struct dm_message_vi
|
||||
memcpy(&view.conv, body, 8); memcpy(&view.seq, body + 8, 8);
|
||||
memcpy(&view.timestamp, body + 16, 8); memcpy(&view.author, body + 24, 8);
|
||||
view.content_type_size = body[32];
|
||||
if (!view.content_type_size) {
|
||||
if (available - pos < (size_t)view.content_type_size + 2) return protocol_error("content type length");
|
||||
view.content_type = body + pos; pos += view.content_type_size;
|
||||
memcpy(&view.ciphertext_size, body + pos, 2); pos += 2;
|
||||
if (view.ciphertext_size & DM_CONTEXT_FLAG) {
|
||||
view.mode = DM_MODE_GROUPS;
|
||||
view.ciphertext_size &= ~DM_CONTEXT_FLAG;
|
||||
if (available - pos < 1 + 2 * DM_PARTY_WIRE_SIZE + 2 || body[pos++] != 1) return protocol_error("context version/size");
|
||||
if (dm_party_decode(body + pos, view.parties) || dm_party_decode(body + pos + DM_PARTY_WIRE_SIZE, view.parties + 1))
|
||||
return protocol_error("context parties");
|
||||
@@ -32,14 +36,9 @@ int dm_message_parse(const uint8_t* body, size_t available, struct dm_message_vi
|
||||
view.target_count = (uint16_t)(body[pos] | ((uint16_t)body[pos + 1] << 8)); pos += 2;
|
||||
if (view.target_count < 2 || view.target_count > DM_TARGET_MAX) return protocol_error("target count");
|
||||
size_t targets_size = (size_t)view.target_count * DM_TARGET_PROOF_SIZE;
|
||||
if (available - pos < targets_size + 1) return protocol_error("target list length");
|
||||
if (available - pos < targets_size) return protocol_error("target list length");
|
||||
view.targets = body + pos; pos += targets_size;
|
||||
view.content_type_size = body[pos++];
|
||||
if (!view.content_type_size) return protocol_error("empty content type");
|
||||
}
|
||||
if (available - pos < (size_t)view.content_type_size + 2) return protocol_error("content type length");
|
||||
view.content_type = body + pos; pos += view.content_type_size;
|
||||
memcpy(&view.ciphertext_size, body + pos, 2); pos += 2;
|
||||
if (view.ciphertext_size < 16 || view.ciphertext_size > 1024 + 16 || available - pos < view.ciphertext_size)
|
||||
return protocol_error("ciphertext length");
|
||||
view.ciphertext = body + pos; pos += view.ciphertext_size;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* dm_protocol — единый разбор тела DEVICE/GROUPS и сертификатов адресатов.
|
||||
* DEVICE сохраняет существующий формат. GROUPS занимает зарезервированный
|
||||
* ct_len=0 и помещает типизированные стороны/адресатов перед настоящим ct.
|
||||
* DEVICE сохраняет существующий формат, включая пустой content type. GROUPS
|
||||
* ставит старший бит data_len и помещает контекст перед ciphertext.
|
||||
* Тело подписывается целиком, включая снимок; parser не проверяет подпись автора.
|
||||
* Указатели view заимствуют входной буфер. SQL-функция encode вызывается в uasync. */
|
||||
#ifndef UTUN_DM_PROTOCOL_H
|
||||
@@ -13,8 +13,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define DM_TARGET_PROOF_SIZE 137 /* node:LE64,side:u8,x:32,ed:32,member_sig:64. */
|
||||
#define DM_CONTEXT_FLAG 0x8000u /* Старший бит uint16 data_len; фактическая длина не более1040. */
|
||||
#define DM_CONTEXT_MAX (1 + 2 * DM_PARTY_WIRE_SIZE + 2 + DM_TARGET_MAX * DM_TARGET_PROOF_SIZE)
|
||||
#define DM_BODY_MAX (33 + DM_CONTEXT_MAX + 1 + 255 + 2 + 1024 + 16 + 56 + 64)
|
||||
#define DM_BODY_MAX (33 + 255 + 2 + DM_CONTEXT_MAX + 1024 + 16 + 56 + 64)
|
||||
|
||||
struct dm_message_view {
|
||||
uint64_t conv, seq, timestamp, author; /* Общий префикс, native-endian. */
|
||||
@@ -46,7 +47,7 @@ int dm_message_target(const struct dm_message_view* view, uint64_t node, uint8_t
|
||||
/* 0/-1: прочитать node/side по индексу GROUPS-snapshot, без проверки подписи. */
|
||||
int dm_message_target_at(const struct dm_message_view* view, unsigned index, struct dm_target* out);
|
||||
|
||||
/* 0/-1: сформировать контекст GROUPS (без префикса сообщения/нулевого ct_len).
|
||||
/* 0/-1: сформировать контекст GROUPS (между data_len с флагом и ciphertext).
|
||||
* VERSION=1:u8, parties:2*73,count:LE16,sorted certificates:count*137.
|
||||
* Сторона 0 должна включать текущего отправителя. out меняется только при успехе;
|
||||
* DM_CONTEXT_MAX достаточно. Источник включается, неизвестные устройства не ищутся. */
|
||||
|
||||
Reference in new issue
Block a user