diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 23f0b98d..d16cd938 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -95,6 +95,12 @@ #ifdef HAVE_OMEMO #include "omemo/omemo.h" #include "xmpp/omemo.h" + +#define AESGCM_URL_SCHEME "aesgcm" +#define AESGCM_URL_NONCE_LEN 24 +#define AESGCM_URL_KEY_LEN 64 +#define AESGCM_URL_FRAGMENT_LEN \ + (size_t)(AESGCM_URL_NONCE_LEN + AESGCM_URL_KEY_LEN) #endif #ifdef HAVE_GTK @@ -4806,6 +4812,21 @@ cmd_disco(ProfWin* window, const char* const command, gchar** args) return TRUE; } +char *create_aesgcm_fragment(unsigned char *key, int key_size, + unsigned char *nonce, int nonce_size) { + char fragment[(nonce_size+key_size)*2+1]; + + for (int i = 0; i < nonce_size; i++) { + sprintf(&(fragment[i*2]), "%02x", nonce[i]); + } + + for (int i = 0; i < key_size; i++) { + sprintf(&(fragment[(i+nonce_size)*2]), "%02x", key[i]); + } + + return strdup(fragment); +} + gboolean cmd_sendfile(ProfWin* window, const char* const command, gchar** args) { @@ -4849,6 +4870,8 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) } FILE *fh = fdopen(fd, "rb"); + char *alt_scheme = NULL; + char *alt_fragment = NULL; switch (window->type) { case WIN_MUC: @@ -4898,12 +4921,17 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) fflush(tmpfh); rewind(tmpfh); - fclose(fh); + fclose(fh); // Also closes descriptor. // Switch original stream with temporary encrypted stream. fd = tmpfd; fh = tmpfh; + alt_scheme = AESGCM_URL_SCHEME; + alt_fragment = create_aesgcm_fragment( + key, AES256_GCM_KEY_LENGTH, + nonce, AES256_GCM_NONCE_LENGTH); + break; } @@ -4944,6 +4972,8 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) upload->filehandle = fh; upload->filesize = file_size(fd); upload->mime_type = file_mime_type(filename); + upload->alt_scheme = alt_scheme; + upload->alt_fragment = alt_fragment; iq_http_upload_request(upload); diff --git a/src/tools/http_upload.c b/src/tools/http_upload.c index 5f725851..69587c08 100644 --- a/src/tools/http_upload.c +++ b/src/tools/http_upload.c @@ -128,8 +128,35 @@ _data_callback(void* ptr, size_t size, size_t nmemb, void* data) return realsize; } -void* -http_file_put(void* userdata) +int format_alt_url(char *original_url, char *new_scheme, char *new_fragment, char **new_url) { + int ret = 0; + CURLU *h = curl_url(); + + if ((ret = curl_url_set(h, CURLUPART_URL, original_url, 0)) != 0) { + goto out; + } + + if (new_scheme != NULL) { + if ((ret = curl_url_set(h, CURLUPART_SCHEME, new_scheme, CURLU_NON_SUPPORT_SCHEME)) != 0) { + goto out; + } + } + + if (new_fragment != NULL) { + if ((ret = curl_url_set(h, CURLUPART_FRAGMENT, new_fragment, 0)) != 0) { + goto out; + } + } + + ret = curl_url_get(h, CURLUPART_URL, new_url, 0); + +out: + curl_url_cleanup(h); + return ret; +} + +void * +http_file_put(void *userdata) { HTTPUpload* upload = (HTTPUpload*)userdata; @@ -256,30 +283,40 @@ http_file_put(void* userdata) win_mark_received(upload->window, upload->put_url); free(msg); - switch (upload->window->type) { - case WIN_CHAT: - { - ProfChatWin* chatwin = (ProfChatWin*)(upload->window); - assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - cl_ev_send_msg(chatwin, upload->get_url, upload->get_url); - break; - } - case WIN_PRIVATE: - { - ProfPrivateWin* privatewin = (ProfPrivateWin*)(upload->window); - assert(privatewin->memcheck == PROFPRIVATEWIN_MEMCHECK); - cl_ev_send_priv_msg(privatewin, upload->get_url, upload->get_url); - break; - } - case WIN_MUC: - { - ProfMucWin* mucwin = (ProfMucWin*)(upload->window); - assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - cl_ev_send_muc_msg(mucwin, upload->get_url, upload->get_url); - break; - } - default: - break; + char *url = NULL; + if (format_alt_url(upload->get_url, upload->alt_scheme, upload->alt_fragment, &url) != 0) { + char *msg; + asprintf(&msg, "Uploading '%s' failed: Bad URL ('%s')", upload->filename, upload->get_url); + cons_show_error(msg); + free(msg); + } else { + switch (upload->window->type) { + case WIN_CHAT: + { + ProfChatWin *chatwin = (ProfChatWin*)(upload->window); + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + cl_ev_send_msg(chatwin, url, url); + break; + } + case WIN_PRIVATE: + { + ProfPrivateWin *privatewin = (ProfPrivateWin*)(upload->window); + assert(privatewin->memcheck == PROFPRIVATEWIN_MEMCHECK); + cl_ev_send_priv_msg(privatewin, url, url); + break; + } + case WIN_MUC: + { + ProfMucWin *mucwin = (ProfMucWin*)(upload->window); + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + cl_ev_send_muc_msg(mucwin, url, url); + break; + } + default: + break; + } + + curl_free(url); } } } diff --git a/src/tools/http_upload.h b/src/tools/http_upload.h index 5b3b4754..9e801973 100644 --- a/src/tools/http_upload.h +++ b/src/tools/http_upload.h @@ -50,10 +50,12 @@ typedef struct http_upload_t { FILE *filehandle; off_t filesize; curl_off_t bytes_sent; - char* mime_type; - char* get_url; - char* put_url; - ProfWin* window; + char *mime_type; + char *get_url; + char *put_url; + char *alt_scheme; + char *alt_fragment; + ProfWin *window; pthread_t worker; int cancel; } HTTPUpload;