diff --git a/src/dm/dm_core.c b/src/dm/dm_core.c index 9e01260c0..72274b46b 100644 --- a/src/dm/dm_core.c +++ b/src/dm/dm_core.c @@ -440,7 +440,9 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t data += DM_MEDIA_DESC_SIZE; data_len -= DM_MEDIA_DESC_SIZE; struct attachment_info info; - if (attachment_decode(data, data_len, &info)) return -1; + const uint8_t* keys; + if (dm_media_metadata_decode(data, data_len, &info, &keys)) return -1; + if (c->mode == DM_MODE_GROUPS && !keys) { DEBUG_WARN(DEBUG_CATEGORY_DM, "DM file: GROUPS keys required"); return -1; } } uint64_t conv_num = (uint64_t)strtoull(c->conv_id, NULL, 10); uint8_t nonce[DM_NONCE_SIZE]; @@ -635,7 +637,9 @@ int dm_accept_message(struct UTUN_INSTANCE* inst, const uint8_t* msg, size_t len if (media_ccm_decrypt(c.content_key, nonce, message.ciphertext, message.ciphertext_size, plain, &plain_len) != 0) return -1; if (dm_message_media(msg, len)) { struct attachment_info info; - if (attachment_decode(plain, plain_len, &info)) return -1; + const uint8_t* keys; + if (dm_media_metadata_decode(plain, plain_len, &info, &keys)) return -1; + if (c.mode == DM_MODE_GROUPS && !keys) { DEBUG_WARN(DEBUG_CATEGORY_DM, "DM file: missing GROUPS key wraps"); return -1; } } if (dm_exec(dm, "BEGIN IMMEDIATE") != 0) return -1; int inserted = dm_store_message(dm, conv_id, dir, msg, len); @@ -1245,7 +1249,8 @@ int dm_list_messages_json(struct UTUN_INSTANCE* inst, const char* conv_id, int c struct attachment_info attachment = {0}; int file = ct && !strcmp(ct, "file"); if (file) { - if (attachment_decode((const uint8_t*)text, plen, &attachment)) goto fail; + const uint8_t* keys; + if (dm_media_metadata_decode((const uint8_t*)text, plen, &attachment, &keys)) goto fail; snprintf(text, sizeof(text), "%s", attachment.name); } int ready = sqlite3_column_int(st, 7), downloading = sqlite3_column_int(st, 8); diff --git a/src/dm/dm_media.c b/src/dm/dm_media.c index 53275d20d..a6d6565ba 100644 --- a/src/dm/dm_media.c +++ b/src/dm/dm_media.c @@ -681,7 +681,6 @@ static void dm_file_done(void* arg, int error) { uint8_t stored[24]; memcpy(stored, job->id, 16); memcpy(stored + 16, &expires, 8); dm_media_send(inst, group, peer, DM_MEDIA_STORED, stored, sizeof(stored)); } else { - dm_file_remove(job->cipher); dm_media_send(inst, group, peer, DM_MEDIA_RECEIPT, receipt, sizeof(receipt)); dm_mailbox_media_receipt(inst, receipt); uint64_t conv; memcpy(&conv, body, 8); dm_media_notify(inst, conv); @@ -724,26 +723,27 @@ static void dm_file_pull(struct dm_media_state* media, int custody, uint64_t gro if (!job) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "dm_media: download allocation failed"); return; } job->media = media; job->work = custody ? DM_FILE_CUSTODY : DM_FILE_RECEIVE; job->author = author; memcpy(job->id, desc, 16); memcpy(&job->size, desc + 16, 8); memcpy(job->hash, desc + 24, 32); - if (dm_file_path(media, custody, job->id, ".download", job->cipher, sizeof(job->cipher)) || + if (dm_file_path(media, custody, job->id, custody ? ".download" : ".cipher", job->cipher, sizeof(job->cipher)) || dm_file_path(media, custody, job->id, ".decrypt", job->temp, sizeof(job->temp)) || dm_file_path(media, custody, job->id, custody ? ".cipher" : ".file", job->output, sizeof(job->output))) { u_free(job); return; } if (!custody) { - snprintf(job->conv, sizeof(job->conv), "%llu", (unsigned long long)dm_derive_conv_id(media->inst->node_id, author)); - job->generation = dm_history_generation(media->inst, job->conv); - if (dm_job_hold(job)) { dm_job_free(job); return; } - sqlite3_stmt* st = dm_media_prepare(media->inst, "SELECT x25519_pubkey FROM nodes WHERE node_id=?"); + sqlite3_stmt* st = dm_media_prepare(media->inst, "SELECT conv_id,body FROM dm_files WHERE id=? AND dir=0"); if (!st) { dm_job_free(job); return; } - sqlite3_bind_int64(st, 1, (sqlite3_int64)author); + sqlite3_bind_blob(st, 1, job->id, 16, SQLITE_STATIC); int rc = sqlite3_step(st); - uint8_t pub[32]; - int found = rc == SQLITE_ROW && sqlite3_column_bytes(st, 0) == sizeof(pub); - if (found) memcpy(pub, sqlite3_column_blob(st, 0), sizeof(pub)); + int found = rc == SQLITE_ROW; + if (found) { + snprintf(job->conv, sizeof(job->conv), "%s", sqlite3_column_text(st, 0)); + found = !dm_file_key(media->inst, sqlite3_column_blob(st, 1), (size_t)sqlite3_column_bytes(st, 1), job->key); + } sqlite3_finalize(st); - if (!found || dm_derive_content_key(media->inst->my_keys.private_key, pub, job->key)) { + if (!found) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "dm_media: target key unavailable author=%llu", (unsigned long long)author); dm_job_free(job); return; } + job->generation = dm_history_generation(media->inst, job->conv); + if (dm_job_hold(job)) { dm_job_free(job); return; } } job->next = media->jobs; media->jobs = job; job->transfer = file_transfer_pull(media->inst->file_transfer, group, peer, job->id, dm_media_cipher_size(job->size),