mirror of
https://git.jabber.space/devs/cproof.git
synced 2026-07-24 11:36:21 +00:00
Merge profanity-im/profanity master (373 commits) into cproof fork.
Source changes (manual merge):
- src/command/: cmd_defs, cmd_funcs, cmd_ac — upstream g_new0, auto_gchar,
launch_editor callback; keep our XEP-0308 LMC, force-encryption, CWE-134
- src/config/: preferences, tlscerts, account — upstream UNIQUE dedup,
dynamic pad capacity; keep our db_history_result_t, scroll logic
- src/database.*: upstream g_new0 memory mgmt; keep our return types,
add null-check fix for msg->timestamp
- src/omemo/, src/pgp/: upstream _gpgme_key_get_email, g_new0;
keep our replace_id in omemo_on_message_send
- src/tools/: editor, http_upload, bookmark_ignore — upstream launch_editor
callback API
- src/ui/: console, window, chatwin, mucwin, inputwin, buffer —
upstream win_warn_needed/sent dedup, PAD_MIN_HEIGHT dynamic pads;
keep our y_start_pos scroll, _truncate_datetime_suffix
- src/xmpp/: message, stanza, presence, roster_list, iq, session —
upstream connection_get_available_resources; keep our LMC stanza logic
- src/common.c: fix format-security (cons_show)
Build system:
- Makefile.am: updated test paths to subdirectory structure, added
test_cmd_ac, test_forced_encryption
- Restored autotools files deleted by upstream meson migration:
bootstrap.sh, autogen.sh, m4/ax_valgrind_check.m4, configure-debug
Tests:
- Unit tests: upstream unittests.c base + our forced_encryption tests
(482 passed, 0 failed across all 4 configurations)
- Functional tests: kept our version (93 passed, 0 failed)
upstream version requires stbbr_for_xmlns not yet in our stabber fork
- Updated test stubs: stub_xmpp.c, stub_omemo.c from upstream
Compile fixes:
- src/common.c: cons_show(errmsg) -> cons_show("%s", errmsg)
- src/database.c: null-check before msg->timestamp access
- src/ui/console.c: size_t -> (int) cast for format width
- src/config/tlscerts.c: %d -> %zu for size_t
165 lines
5.9 KiB
C
165 lines
5.9 KiB
C
/*
|
|
* aesgcm_download.c
|
|
* vim: expandtab:ts=4:sts=4:sw=4
|
|
*
|
|
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
|
* Copyright (C) 2020 William Wennerström <william@wstrm.dev>
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <curl/curl.h>
|
|
#include <gio/gio.h>
|
|
#include <pthread.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
#include "profanity.h"
|
|
#include "event/client_events.h"
|
|
#include "tools/http_common.h"
|
|
#include "tools/aesgcm_download.h"
|
|
#include "omemo/omemo.h"
|
|
#include "config/preferences.h"
|
|
#include "ui/ui.h"
|
|
#include "ui/window.h"
|
|
#include "common.h"
|
|
|
|
void*
|
|
aesgcm_file_get(void* userdata)
|
|
{
|
|
AESGCMDownload* aesgcm_dl = (AESGCMDownload*)userdata;
|
|
|
|
auto_char char* https_url = NULL;
|
|
auto_char char* fragment = NULL;
|
|
|
|
// Convert the aesgcm:// URL to a https:// URL and extract the encoded key
|
|
// and tag stored in the URL fragment.
|
|
if (omemo_parse_aesgcm_url(aesgcm_dl->url, &https_url, &fragment) != 0) {
|
|
cons_show_error("Download failed: Cannot parse URL '%s'.", aesgcm_dl->url);
|
|
http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR,
|
|
"Download failed: Cannot parse URL '%s'.",
|
|
aesgcm_dl->url);
|
|
return NULL;
|
|
}
|
|
|
|
// Create a temporary file used for storing the ciphertext that is to be
|
|
// retrieved from the https:// URL.
|
|
auto_gchar gchar* tmpname = NULL;
|
|
auto_gfd gint tmpfd = 0;
|
|
if ((tmpfd = g_file_open_tmp("profanity.XXXXXX", &tmpname, NULL)) == -1) {
|
|
http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR,
|
|
"Downloading '%s' failed: Unable to create "
|
|
"temporary ciphertext file for writing "
|
|
"(%s).",
|
|
https_url, g_strerror(errno));
|
|
return NULL;
|
|
}
|
|
|
|
// Open the target file for storing the cleartext.
|
|
auto_FILE FILE* outfh = fopen(aesgcm_dl->filename, "wb");
|
|
if (outfh == NULL) {
|
|
http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR,
|
|
"Downloading '%s' failed: Unable to open "
|
|
"output file at '%s' for writing (%s).",
|
|
https_url, aesgcm_dl->filename,
|
|
g_strerror(errno));
|
|
return NULL;
|
|
}
|
|
|
|
// We wrap the HTTPDownload tool and use it for retrieving the ciphertext
|
|
// and storing it in the temporary file previously opened.
|
|
HTTPDownload* http_dl = g_new0(HTTPDownload, 1);
|
|
http_dl->window = aesgcm_dl->window;
|
|
http_dl->worker = aesgcm_dl->worker;
|
|
http_dl->id = strdup(aesgcm_dl->id);
|
|
http_dl->url = strdup(https_url);
|
|
http_dl->display_url = strdup(aesgcm_dl->url);
|
|
http_dl->filename = strdup(tmpname);
|
|
http_dl->cmd_template = NULL;
|
|
http_dl->silent = FALSE;
|
|
http_dl->silent_done = TRUE;
|
|
http_dl->return_bytes_received = TRUE;
|
|
aesgcm_dl->http_dl = http_dl;
|
|
|
|
ssize_t* p_bytes_received = http_file_get(http_dl);
|
|
if (!p_bytes_received) {
|
|
return NULL;
|
|
}
|
|
ssize_t bytes_received = *p_bytes_received;
|
|
free(p_bytes_received);
|
|
|
|
FILE* tmpfh = fopen(tmpname, "rb");
|
|
if (tmpfh == NULL) {
|
|
http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR,
|
|
"Downloading '%s' failed: Unable to open "
|
|
"temporary file at '%s' for reading (%s).",
|
|
aesgcm_dl->url, tmpname,
|
|
g_strerror(errno));
|
|
return NULL;
|
|
}
|
|
|
|
gcry_error_t crypt_res;
|
|
crypt_res = omemo_decrypt_file(tmpfh, outfh,
|
|
bytes_received, fragment);
|
|
fclose(tmpfh);
|
|
remove(tmpname);
|
|
|
|
if (crypt_res != GPG_ERR_NO_ERROR) {
|
|
http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR,
|
|
"Downloading '%s' failed: Failed to decrypt "
|
|
"file (%s).",
|
|
https_url, gcry_strerror(crypt_res));
|
|
} else {
|
|
http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ONLINE, ENTRY_COMPLETED,
|
|
"Downloading '%s': done\nSaved to '%s'",
|
|
aesgcm_dl->url, aesgcm_dl->filename);
|
|
win_mark_received(aesgcm_dl->window, aesgcm_dl->id);
|
|
}
|
|
|
|
if (aesgcm_dl->cmd_template != NULL) {
|
|
gchar** argv = format_call_external_argv(aesgcm_dl->cmd_template,
|
|
aesgcm_dl->filename,
|
|
aesgcm_dl->filename);
|
|
|
|
// TODO: Log the error.
|
|
if (!call_external(argv)) {
|
|
http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR,
|
|
"Downloading '%s' failed: Unable to call "
|
|
"command '%s' with file at '%s' (%s).",
|
|
aesgcm_dl->url,
|
|
aesgcm_dl->cmd_template,
|
|
aesgcm_dl->filename,
|
|
"TODO: Log the error");
|
|
}
|
|
|
|
g_strfreev(argv);
|
|
free(aesgcm_dl->cmd_template);
|
|
}
|
|
|
|
free(aesgcm_dl->id);
|
|
free(aesgcm_dl->filename);
|
|
free(aesgcm_dl->url);
|
|
free(aesgcm_dl);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
aesgcm_download_cancel_processes(ProfWin* window)
|
|
{
|
|
http_download_cancel_processes(window);
|
|
}
|
|
|
|
void
|
|
aesgcm_download_add_download(AESGCMDownload* aesgcm_dl)
|
|
{
|
|
http_download_add_download(aesgcm_dl->http_dl);
|
|
}
|