Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package otpclient for openSUSE:Factory checked in at 2022-12-30 11:08:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/otpclient (Old)
and /work/SRC/openSUSE:Factory/.otpclient.new.1563 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "otpclient"
Fri Dec 30 11:08:53 2022 rev:21 rq:1045797 version:3.1.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/otpclient/otpclient.changes 2022-12-20 20:21:03.782067662 +0100
+++ /work/SRC/openSUSE:Factory/.otpclient.new.1563/otpclient.changes 2022-12-30 11:09:08.201318769 +0100
@@ -1,0 +2,8 @@
+Fri Dec 30 07:06:40 UTC 2022 - Paolo Stivanin
+
+- Update to 3.1.1:
+ * Fixed some memory leaks.
+ * Improved error handling.
+ * Use secure functions instead of standard ones .
+
+-------------------------------------------------------------------
Old:
----
v3.1.0.tar.gz
v3.1.0.tar.gz.asc
New:
----
v3.1.1.tar.gz
v3.1.1.tar.gz.asc
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ otpclient.spec ++++++
--- /var/tmp/diff_new_pack.huiRqu/_old 2022-12-30 11:09:08.609321208 +0100
+++ /var/tmp/diff_new_pack.huiRqu/_new 2022-12-30 11:09:08.613321232 +0100
@@ -18,7 +18,7 @@
%define uclname OTPClient
Name: otpclient
-Version: 3.1.0
+Version: 3.1.1
Release: 0
Summary: Simple GTK+ client for managing TOTP and HOTP
License: GPL-3.0-or-later
++++++ v3.1.0.tar.gz -> v3.1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/.github/workflows/codeql-analysis.yml new/OTPClient-3.1.1/.github/workflows/codeql-analysis.yml
--- old/OTPClient-3.1.0/.github/workflows/codeql-analysis.yml 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/.github/workflows/codeql-analysis.yml 2022-12-28 17:02:45.000000000 +0100
@@ -24,7 +24,7 @@
uses: actions/checkout@v2
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
@@ -41,4 +41,4 @@
make
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@v2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/CMakeLists.txt new/OTPClient-3.1.1/CMakeLists.txt
--- old/OTPClient-3.1.0/CMakeLists.txt 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/CMakeLists.txt 2022-12-28 17:02:45.000000000 +0100
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
-project(OTPClient VERSION "3.1.0" LANGUAGES "C")
+project(OTPClient VERSION "3.1.1" LANGUAGES "C")
include(GNUInstallDirs)
configure_file("src/common/version.h.in" "version.h")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/README.md new/OTPClient-3.1.1/README.md
--- old/OTPClient-3.1.0/README.md 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/README.md 2022-12-28 17:02:45.000000000 +0100
@@ -2,6 +2,10 @@
<a href="https://circleci.com/gh/paolostivanin/OTPClient">
<img alt="CircleCI" src="https://circleci.com/gh/paolostivanin/OTPClient.svg?style=svg"/>
</a>
+<a href="https://scan.coverity.com/projects/paolostivanin-otpclient">
+
+</a>
Highly secure and easy to use GTK+ software for two-factor authentication that supports both Time-based One-time Passwords (TOTP) and HMAC-Based One-Time Passwords (HOTP).
@@ -42,7 +46,7 @@
- decrypted file is never saved (and hopefully never swapped) to disk. While the app is running, the decrypted content resides in a "secure memory" buffer allocated by Gcrypt
## Testing
-* Before each release, I run PVS Studio in order to catch even more errors and/or corner cases
+* Before each release, I run PVS Studio and Coverity in order to catch even more bugs.
* With every commit to master, OTPClient is compiled in CircleCI against different distros
## Protobuf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/data/com.github.paolostivanin.OTPClient.appdata.xml new/OTPClient-3.1.1/data/com.github.paolostivanin.OTPClient.appdata.xml
--- old/OTPClient-3.1.0/data/com.github.paolostivanin.OTPClient.appdata.xml 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/data/com.github.paolostivanin.OTPClient.appdata.xml 2022-12-28 17:02:45.000000000 +0100
@@ -83,6 +83,16 @@
<releases>
+ <release version="3.1.1" date="2022-12-29">
+ <description>
+ <p>OTPClient 3.1.1 brings lots of small under-the-hood changes:</p>
+ <ul>
+ <li>Fixed some memory leaks</li>
+ <li>Improved error handling</li>
+ <li>Use secure functions instead of standard ones</li>
+ </ul>
+ </description>
+ </release>
<release version="3.1.0" date="2022-12-19">
<description>
<p>OTPClient 3.1.0 the following feature and fixes:</p>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/add-common.c new/OTPClient-3.1.1/src/add-common.c
--- old/OTPClient-3.1.0/src/add-common.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/add-common.c 2022-12-28 17:02:45.000000000 +0100
@@ -47,6 +47,7 @@
if (otp->period < 10 || otp->period > 120) {
gchar *msg = g_strconcat("[INFO]: invalid period for '", otp->account_name, "'. Defaulting back to 30 seconds.", NULL);
g_printerr ("%s\n", msg);
+ g_free (msg);
otp->period = 30;
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/add-from-qr.c new/OTPClient-3.1.1/src/add-from-qr.c
--- old/OTPClient-3.1.0/src/add-from-qr.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/add-from-qr.c 2022-12-28 17:02:45.000000000 +0100
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
#include "imports.h"
#include "qrcode-parser.h"
#include "message-dialogs.h"
@@ -169,7 +170,9 @@
gchar *filename = g_build_filename (g_get_tmp_dir (), "qrcode_from_cb_uri.png", NULL);
gdk_pixbuf_save (pbuf, filename, "png", &err, NULL);
parse_file_and_update_db (filename, app_data, FALSE);
- g_unlink (filename);
+ if (g_unlink (filename) == -1) {
+ g_printerr ("%s\n", _("Couldn't unlink the temp pixbuf."));
+ }
g_free (filename);
g_object_unref (pbuf);
}
@@ -196,7 +199,9 @@
} else {
parse_file_and_update_db (filename, app_data, FALSE);
}
- g_unlink (filename);
+ if (g_unlink (filename) == -1) {
+ g_printerr ("%s\n", _("Error while unlinking the temp png."));
+ }
g_free (filename);
} else {
show_message_dialog (app_data->main_window, "Couldn't get QR code image from clipboard", GTK_MESSAGE_ERROR);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/app.c new/OTPClient-3.1.1/src/app.c
--- old/OTPClient-3.1.0/src/app.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/app.c 2022-12-28 17:02:45.000000000 +0100
@@ -356,6 +356,7 @@
return kf;
}
g_printerr ("%s\n", err->message);
+ g_clear_error (&err);
}
g_free (cfg_file_path);
g_key_file_free (kf);
@@ -419,6 +420,7 @@
#endif
if (!g_key_file_save_to_file (kf, cfg_file_path, &err)) {
g_printerr ("%s\n", err->message);
+ g_clear_error (&err);
}
g_free (cfg_file_path);
g_key_file_free (kf);
@@ -492,9 +494,9 @@
#else
cfg_file_path = g_build_filename (g_get_user_data_dir (), "otpclient.cfg", NULL);
#endif
- g_key_file_save_to_file (kf, cfg_file_path, &err);
- if (err != NULL) {
+ if (!g_key_file_save_to_file (kf, cfg_file_path, &err)) {
g_printerr ("%s\n", err->message);
+ g_clear_error (&err);
}
g_free (cfg_file_path);
}
@@ -568,9 +570,10 @@
if (!g_key_file_load_from_file (kf, cfg_file_path, G_KEY_FILE_NONE, &err)) {
show_message_dialog (app_data->main_window, err->message, GTK_MESSAGE_ERROR);
g_key_file_free (kf);
+ g_clear_error (&err);
return NULL;
}
- db_path = g_key_file_get_string (kf, "config", "db_path", &err);
+ db_path = g_key_file_get_string (kf, "config", "db_path", NULL);
if (db_path == NULL) {
goto new_db;
}
@@ -601,9 +604,9 @@
if (res == GTK_RESPONSE_ACCEPT) {
db_path = gtk_file_chooser_get_filename (chooser);
g_key_file_set_string (kf, "config", "db_path", db_path);
- g_key_file_save_to_file (kf, cfg_file_path, &err);
- if (err != NULL) {
+ if (!g_key_file_save_to_file (kf, cfg_file_path, &err)) {
g_printerr ("%s\n", err->message);
+ g_clear_error (&err);
}
}
@@ -764,11 +767,13 @@
if (g_file_test (cfg_file_path, G_FILE_TEST_EXISTS)) {
if (!g_key_file_load_from_file (kf, cfg_file_path, G_KEY_FILE_NONE, &err)) {
g_printerr ("%s\n", err->message);
+ g_clear_error (&err);
} else {
g_key_file_set_integer (kf, "config", param1_name, param1_value);
g_key_file_set_integer (kf, "config", param2_name, param2_value);
if (!g_key_file_save_to_file (kf, cfg_file_path, &err)) {
g_printerr ("%s\n", err->message);
+ g_clear_error (&err);
}
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/change-file-cb.c new/OTPClient-3.1.1/src/change-file-cb.c
--- old/OTPClient-3.1.0/src/change-file-cb.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/change-file-cb.c 2022-12-28 17:02:45.000000000 +0100
@@ -1,5 +1,7 @@
#include
+#include
#include "db-misc.h"
+#include "message-dialogs.h"
gboolean
change_file (AppData *app_data)
@@ -40,7 +42,13 @@
cfg_file_path = g_build_filename (g_get_user_data_dir (), "otpclient.cfg", NULL);
#endif
g_key_file_set_string (kf, "config", "db_path", db_path);
- g_key_file_save_to_file (kf, cfg_file_path, NULL);
+ GError *err = NULL;
+ if (!g_key_file_save_to_file (kf, cfg_file_path, &err)) {
+ gchar *err_msg = g_strconcat (_("Couldn't save the config file: "), err->message, NULL);
+ show_message_dialog (app_data->main_window, err_msg, GTK_MESSAGE_ERROR);
+ g_free (err_msg);
+ g_clear_error (&err);
+ }
g_free (app_data->db_data->db_path);
app_data->db_data->db_path = g_strdup (db_path);
g_free (db_path);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/change-pwd-cb.c new/OTPClient-3.1.1/src/change-pwd-cb.c
--- old/OTPClient-3.1.0/src/change-pwd-cb.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/change-pwd-cb.c 2022-12-28 17:02:45.000000000 +0100
@@ -27,6 +27,7 @@
GtkApplication *app = gtk_window_get_application (GTK_WINDOW(app_data->main_window));
destroy_cb (app_data->main_window, app_data);
g_application_quit (G_APPLICATION(app));
+ return;
}
show_message_dialog (app_data->main_window, "Password successfully changed", GTK_MESSAGE_INFO);
secret_password_store (OTPCLIENT_SCHEMA, SECRET_COLLECTION_DEFAULT, "main_pwd", app_data->db_data->key, NULL, on_password_stored, NULL, "string", "main_pwd", NULL);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/cli/main.c new/OTPClient-3.1.1/src/cli/main.c
--- old/OTPClient-3.1.0/src/cli/main.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/cli/main.c 2022-12-28 17:02:45.000000000 +0100
@@ -206,9 +206,10 @@
if (!g_key_file_load_from_file (kf, cfg_file_path, G_KEY_FILE_NONE, &err)) {
g_printerr ("%s\n", err->message);
g_key_file_free (kf);
+ g_clear_error (&err);
return NULL;
}
- db_path = g_key_file_get_string (kf, "config", "db_path", &err);
+ db_path = g_key_file_get_string (kf, "config", "db_path", NULL);
if (db_path == NULL) {
goto type_db_path;
}
@@ -226,6 +227,7 @@
if (fgets (db_path, MAX_ABS_PATH_LEN, stdin) == NULL) {
g_printerr ("%s\n", _("Couldn't get db path from stdin"));
g_free (cfg_file_path);
+ g_free (db_path);
return NULL;
} else {
// remove the newline char
@@ -233,6 +235,7 @@
if (!g_file_test (db_path, G_FILE_TEST_EXISTS)) {
g_printerr (_("File '%s' does not exist\n"), db_path);
g_free (cfg_file_path);
+ g_free (db_path);
return NULL;
}
}
@@ -291,6 +294,7 @@
if (!g_key_file_load_from_file (kf, cfg_file_path, G_KEY_FILE_NONE, &err)) {
g_printerr ("%s\n", err->message);
g_key_file_free (kf);
+ g_clear_error (&err);
return FALSE;
}
disable_secret_service = g_key_file_get_boolean (kf, "config", "disable_secret_service", NULL);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/common/aegis.c new/OTPClient-3.1.1/src/common/aegis.c
--- old/OTPClient-3.1.0/src/common/aegis.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/common/aegis.c 2022-12-28 17:02:45.000000000 +0100
@@ -90,12 +90,25 @@
guchar *key_tag = hexstr_to_bytes (json_string_value (json_object_get (kp, "tag")));
json_t *dbp = json_object_get(json_object_get(json, "header"), "params");
guchar *keybuf = gcry_malloc (KEY_SIZE);
- gcry_kdf_derive (password, strlen (password) + 1, GCRY_KDF_SCRYPT, n, salt, SALT_SIZE, p, KEY_SIZE, keybuf);
+ if (gcry_kdf_derive (password, strlen (password) + 1, GCRY_KDF_SCRYPT, n, salt, SALT_SIZE, p, KEY_SIZE, keybuf) != 0) {
+ g_printerr ("Error while deriving the key.\n");
+ g_free (salt);
+ g_free (enc_key);
+ g_free (key_nonce);
+ g_free (key_tag);
+ gcry_free (keybuf);
+ return NULL;
+ }
- gcry_cipher_hd_t hd;
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0);
- gcry_cipher_setkey (hd, keybuf, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, key_nonce, NONCE_SIZE);
+ gcry_cipher_hd_t hd = open_cipher_and_set_data (keybuf, key_nonce, NONCE_SIZE);
+ if (hd == NULL) {
+ g_free (salt);
+ g_free (enc_key);
+ g_free (key_nonce);
+ g_free (key_tag);
+ gcry_free (keybuf);
+ return NULL;
+ }
guchar *master_key = gcry_calloc_secure (KEY_SIZE, 1);
if (gcry_cipher_decrypt (hd, master_key, KEY_SIZE, enc_key, KEY_SIZE) != 0) {
@@ -104,8 +117,9 @@
g_free (enc_key);
g_free (key_nonce);
g_free (key_tag);
- gcry_cipher_close (hd);
gcry_free (master_key);
+ gcry_free (keybuf);
+ gcry_cipher_close (hd);
return NULL;
}
gpg_error_t gpg_err = gcry_cipher_checktag(hd, key_tag, TAG_SIZE);
@@ -115,8 +129,9 @@
g_free (enc_key);
g_free (key_nonce);
g_free (key_tag);
- gcry_cipher_close (hd);
gcry_free (master_key);
+ gcry_free (keybuf);
+ gcry_cipher_close (hd);
return NULL;
}
@@ -124,37 +139,55 @@
g_free (enc_key);
g_free (key_nonce);
g_free (key_tag);
+ gcry_free (keybuf);
gcry_cipher_close (hd);
guchar *nonce = hexstr_to_bytes (json_string_value (json_object_get (dbp, "nonce")));
guchar *tag = hexstr_to_bytes (json_string_value (json_object_get (dbp, "tag")));
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0);
- gcry_cipher_setkey (hd, master_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, nonce, 12);
+
+ hd = open_cipher_and_set_data (master_key, nonce, 12);
+ if (hd == NULL) {
+ g_free (tag);
+ g_free (nonce);
+ gcry_free (master_key);
+ return NULL;
+ }
+
gsize out_len;
- guchar *b64decoded_db = g_base64_decode (json_string_value (json_object_get(json, "db")), &out_len);
+ guchar *b64decoded_db = g_base64_decode_secure (json_string_value (json_object_get(json, "db")), &out_len);
if (out_len > max_file_size) {
g_set_error (err, file_too_big_gquark (), FILE_TOO_BIG, "File is too big");
- gcry_cipher_close (hd);
+ g_free (tag);
+ g_free (nonce);
gcry_free (master_key);
+ gcry_free (b64decoded_db);
+ gcry_cipher_close (hd);
return NULL;
}
+
gchar *decrypted_db = gcry_calloc_secure (out_len, 1);
- gcry_cipher_decrypt (hd, decrypted_db, out_len, b64decoded_db, out_len);
- gpg_err = gcry_cipher_checktag(hd, tag, TAG_SIZE);
+ gpg_err = gcry_cipher_decrypt (hd, decrypted_db, out_len, b64decoded_db, out_len);
+ if (gpg_err) {
+ goto clean_and_exit;
+ }
+ gpg_err = gcry_cipher_checktag (hd, tag, TAG_SIZE);
if (gpg_err != 0) {
g_set_error (err, bad_tag_gquark (), BAD_TAG_ERRCODE, "Invalid TAG (database). Either the password is wrong or the file is corrupted.");
- gcry_cipher_close (hd);
+ clean_and_exit:
+ g_free (nonce);
+ g_free (tag);
gcry_free (master_key);
- g_free (decrypted_db);
+ gcry_free (decrypted_db);
+ gcry_free (b64decoded_db);
+ gcry_cipher_close (hd);
return NULL;
}
- g_free (b64decoded_db);
g_free (nonce);
g_free (tag);
gcry_cipher_close (hd);
gcry_free (master_key);
+ gcry_free (b64decoded_db);
GSList *otps = parse_json_data (decrypted_db, err);
gcry_free (decrypted_db);
@@ -173,7 +206,7 @@
json_object_set (root, "version", json_integer(1));
gcry_cipher_hd_t hd;
- guchar *derived_master_key, *enc_master_key, *key_nonce, *key_tag, *db_nonce, *db_tag, *salt;
+ guchar *derived_master_key = NULL, *enc_master_key = NULL, *key_nonce = NULL, *key_tag = NULL, *db_nonce = NULL, *db_tag = NULL, *salt = NULL;
json_t *aegis_header_obj = json_object ();
if (password == NULL) {
json_object_set (aegis_header_obj, "slots", json_null ());
@@ -198,18 +231,32 @@
gcry_create_nonce (key_nonce, NONCE_SIZE);
derived_master_key = gcry_calloc_secure(KEY_SIZE, 1);
- gcry_kdf_derive (password, strlen (password) + 1, GCRY_KDF_SCRYPT, 32768, salt, SALT_SIZE, 1, KEY_SIZE, derived_master_key);
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0);
- gcry_cipher_setkey (hd, derived_master_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, key_nonce, NONCE_SIZE);
+ gpg_error_t gpg_err = gcry_kdf_derive (password, strlen (password) + 1, GCRY_KDF_SCRYPT, 32768, salt, SALT_SIZE, 1, KEY_SIZE, derived_master_key);
+ if (gpg_err) {
+ g_printerr ("Error while deriving the key\n");
+ gcry_free (derived_master_key);
+ return NULL;
+ }
+
+ hd = open_cipher_and_set_data (derived_master_key, key_nonce, NONCE_SIZE);
+ if (hd == NULL) {
+ gcry_free (derived_master_key);
+ g_free (key_nonce);
+ g_free (salt);
+ return NULL;
+ }
+
enc_master_key = gcry_malloc (KEY_SIZE);
if (gcry_cipher_encrypt (hd, enc_master_key, KEY_SIZE, derived_master_key, KEY_SIZE)) {
g_printerr ("Error while encrypting the master key.\n");
gcry_free (derived_master_key);
gcry_free (enc_master_key);
+ g_free (key_nonce);
+ g_free (salt);
gcry_cipher_close (hd);
return NULL;
}
+
key_tag = g_malloc0 (TAG_SIZE);
gcry_cipher_gettag (hd, key_tag, TAG_SIZE);
json_object_set (slot_1, "key", json_string (bytes_to_hexstr (enc_master_key, KEY_SIZE)));
@@ -282,9 +329,10 @@
}
if (password != NULL) {
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0);
- gcry_cipher_setkey (hd, derived_master_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, db_nonce, NONCE_SIZE);
+ hd = open_cipher_and_set_data (derived_master_key, db_nonce, NONCE_SIZE);
+ if (hd == NULL) {
+ goto clean_and_return;
+ }
size_t db_size = json_dumpb (aegis_db_obj, NULL, 0, 0);
guchar *enc_db = g_malloc0 (db_size);
gchar *dumped_db = g_malloc0 (db_size);
@@ -292,7 +340,9 @@
if (gcry_cipher_encrypt (hd, enc_db, db_size, dumped_db, db_size)) {
g_printerr ("Error while encrypting the db.\n");
g_free (enc_db);
- gcry_free (dumped_db);
+ g_free (dumped_db);
+ gcry_cipher_close (hd);
+ clean_and_return:
g_free (key_nonce);
g_free (key_tag);
g_free (db_nonce);
@@ -305,7 +355,7 @@
gcry_cipher_gettag (hd, db_tag, TAG_SIZE);
json_t *db_params = json_object_get (aegis_header_obj, "params");
json_object_set (db_params, "tag", json_string (bytes_to_hexstr (db_tag, TAG_SIZE)));
- gcry_free (dumped_db);
+ g_free (dumped_db);
gchar *b64enc_db = g_base64_encode (enc_db, db_size);
json_object_set (root, "db", json_string (b64enc_db));
@@ -318,6 +368,7 @@
g_free (salt);
gcry_free (derived_master_key);
gcry_free (enc_master_key);
+ gcry_cipher_close (hd);
}
FILE *fp = fopen (export_path, "w");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/common/andotp.c new/OTPClient-3.1.1/src/common/andotp.c
--- old/OTPClient-3.1.0/src/common/andotp.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/common/andotp.c 2022-12-28 17:02:45.000000000 +0100
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include "../file-size.h"
#include "../imports.h"
#include "../gquarks.h"
@@ -114,8 +115,8 @@
g_set_error (err, file_too_big_gquark (), FILE_TOO_BIG, "File is too big");
return NULL;
}
- guchar *enc_buf = g_malloc0 (enc_buf_size);
+ guchar *enc_buf = g_malloc0 (enc_buf_size);
if (!g_seekable_seek (G_SEEKABLE (in_stream), 4 + ANDOTP_SALT_SIZE + ANDOTP_IV_SIZE, G_SEEK_SET, NULL, err)) {
g_object_unref (in_stream);
g_object_unref (in_file);
@@ -133,18 +134,28 @@
guchar *derived_key = get_derived_key (password, salt, be_iterations);
- gcry_cipher_hd_t hd;
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, GCRY_CIPHER_SECURE);
- gcry_cipher_setkey (hd, derived_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, iv, ANDOTP_IV_SIZE);
+ gcry_cipher_hd_t hd = open_cipher_and_set_data (derived_key, iv, ANDOTP_IV_SIZE);
+ if (hd == NULL) {
+ gcry_free (derived_key);
+ g_free (enc_buf);
+ return NULL;
+ }
gchar *decrypted_json = gcry_calloc_secure (enc_buf_size, 1);
- gcry_cipher_decrypt (hd, decrypted_json, enc_buf_size, enc_buf, enc_buf_size);
+ gpg_error_t gpg_err = gcry_cipher_decrypt (hd, decrypted_json, enc_buf_size, enc_buf, enc_buf_size);
+ if (gpg_err) {
+ g_free (enc_buf);
+ gcry_free (derived_key);
+ gcry_free (decrypted_json);
+ gcry_cipher_close (hd);
+ return NULL;
+ }
if (gcry_err_code (gcry_cipher_checktag (hd, tag, ANDOTP_TAG_SIZE)) == GPG_ERR_CHECKSUM) {
g_set_error (err, bad_tag_gquark (), BAD_TAG_ERRCODE, "Either the file is corrupted or the password is wrong");
gcry_cipher_close (hd);
- gcry_free (derived_key);
g_free (enc_buf);
+ gcry_free (derived_key);
+ gcry_free (decrypted_json);
return NULL;
}
@@ -240,14 +251,26 @@
guchar *salt = g_malloc0 (ANDOTP_SALT_SIZE);
gcry_create_nonce (salt, ANDOTP_SALT_SIZE);
- gcry_cipher_hd_t hd;
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, GCRY_CIPHER_SECURE);
guchar *derived_key = get_derived_key (password, salt, le_iterations);
- gcry_cipher_setkey (hd, derived_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, iv, ANDOTP_IV_SIZE);
+ gcry_cipher_hd_t hd = open_cipher_and_set_data (derived_key, iv, ANDOTP_IV_SIZE);
+ if (hd == NULL) {
+ gcry_free (derived_key);
+ g_free (iv);
+ g_free (salt);
+ return NULL;
+ }
gchar *enc_buf = gcry_calloc_secure (json_data_size, 1);
- gcry_cipher_encrypt (hd, enc_buf, json_data_size, json_data, json_data_size);
+ gpg_error_t gpg_err = gcry_cipher_encrypt (hd, enc_buf, json_data_size, json_data, json_data_size);
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while encrypting the data."));
+ gcry_free (derived_key);
+ gcry_free (enc_buf);
+ g_free (iv);
+ g_free (salt);
+ gcry_cipher_close (hd);
+ return NULL;
+ }
guchar tag[ANDOTP_TAG_SIZE];
gcry_cipher_gettag (hd, tag, ANDOTP_TAG_SIZE);
gcry_cipher_close (hd);
@@ -257,30 +280,27 @@
if (err != NULL) {
goto cleanup_before_exiting;
}
- g_output_stream_write (G_OUTPUT_STREAM (out_stream), &be_iterations, 4, NULL, &err);
- if (err != NULL) {
+ if (g_output_stream_write (G_OUTPUT_STREAM (out_stream), &be_iterations, 4, NULL, &err) == -1) {
goto cleanup_before_exiting;
}
- g_output_stream_write (G_OUTPUT_STREAM (out_stream), salt, ANDOTP_SALT_SIZE, NULL, &err);
- if (err != NULL) {
+ if (g_output_stream_write (G_OUTPUT_STREAM (out_stream), salt, ANDOTP_SALT_SIZE, NULL, &err) == -1) {
goto cleanup_before_exiting;
}
- g_output_stream_write (G_OUTPUT_STREAM (out_stream), iv, ANDOTP_IV_SIZE, NULL, &err);
- if (err != NULL) {
+ if (g_output_stream_write (G_OUTPUT_STREAM (out_stream), iv, ANDOTP_IV_SIZE, NULL, &err) == -1) {
goto cleanup_before_exiting;
}
- g_output_stream_write (G_OUTPUT_STREAM (out_stream), enc_buf, json_data_size, NULL, &err);
- if (err != NULL) {
+ if (g_output_stream_write (G_OUTPUT_STREAM (out_stream), enc_buf, json_data_size, NULL, &err) == -1) {
goto cleanup_before_exiting;
}
- g_output_stream_write (G_OUTPUT_STREAM (out_stream), tag, ANDOTP_TAG_SIZE, NULL, &err);
- if (err != NULL) {
+ if (g_output_stream_write (G_OUTPUT_STREAM (out_stream), tag, ANDOTP_TAG_SIZE, NULL, &err) == -1) {
goto cleanup_before_exiting;
}
cleanup_before_exiting:
g_free (iv);
+ g_free (salt);
gcry_free (json_data);
+ gcry_free (derived_key);
gcry_free (enc_buf);
json_array_clear (array);
g_object_unref (out_stream);
@@ -299,6 +319,7 @@
guchar *derived_key = gcry_malloc_secure (32);
if (gcry_kdf_derive (password, (gsize) g_utf8_strlen (password, -1), GCRY_KDF_PBKDF2, GCRY_MD_SHA1,
salt, ANDOTP_SALT_SIZE, iterations, 32, derived_key) != 0) {
+ gcry_free (derived_key);
return NULL;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/common/common.c new/OTPClient-3.1.1/src/common/common.c
--- old/OTPClient-3.1.0/src/common/common.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/common/common.c 2022-12-28 17:02:45.000000000 +0100
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include "gcrypt.h"
#include "jansson.h"
#include "../google-migration.pb-c.h"
@@ -92,7 +93,9 @@
json_int_t v = json_integer_value (value);
g_snprintf (tmp_string + strlen (tmp_string), 256, "%ld", (gint64) v);
} else {
- g_strlcat (tmp_string, json_string_value (value), 256);
+ if (g_strlcat (tmp_string, json_string_value (value), 256) > 256) {
+ g_printerr ("%s\n", _("Truncation occurred."));
+ }
}
}
@@ -127,9 +130,9 @@
}
}
sec_buf[pos] = '\0';
- gcry_realloc (sec_buf, g_utf8_strlen(sec_buf, -1) + 1);
+ gchar *secubf_newpos = (gchar *)gcry_realloc (sec_buf, g_utf8_strlen(sec_buf, -1) + 1);
- return sec_buf;
+ return secubf_newpos;
}
@@ -169,6 +172,139 @@
}
+// Backported from Glib 2.68 in order to support Debian "bullseye" and Ubuntu 20.04
+guint
+g_string_replace_backported (GString *string,
+ const gchar *find,
+ const gchar *replace,
+ guint limit)
+{
+ gsize f_len, r_len, pos;
+ gchar *cur, *next;
+ guint n = 0;
+
+ g_return_val_if_fail (string != NULL, 0);
+ g_return_val_if_fail (find != NULL, 0);
+ g_return_val_if_fail (replace != NULL, 0);
+
+ f_len = strlen (find);
+ r_len = strlen (replace);
+ cur = string->str;
+
+ while ((next = strstr (cur, find)) != NULL)
+ {
+ pos = next - string->str;
+ g_string_erase (string, (gssize)pos, (gssize)f_len);
+ g_string_insert (string, (gssize)pos, replace);
+ cur = string->str + pos + r_len;
+ n++;
+ /* Only match the empty string once at any given position, to
+ * avoid infinite loops */
+ if (f_len == 0)
+ {
+ if (cur[0] == '\0')
+ break;
+ else
+ cur++;
+ }
+ if (n == limit)
+ break;
+ }
+
+ return n;
+}
+
+
+// Backported from Glib. The only difference is that it's using gcrypt to allocate a secure buffer.
+static int
+unescape_character (const char *scanner)
+{
+ int first_digit;
+ int second_digit;
+
+ first_digit = g_ascii_xdigit_value (*scanner++);
+ if (first_digit < 0)
+ return -1;
+
+ second_digit = g_ascii_xdigit_value (*scanner++);
+ if (second_digit < 0)
+ return -1;
+
+ return (first_digit << 4) | second_digit;
+}
+
+
+// Backported from Glib. The only difference is that it's using gcrypt to allocate a secure buffer.
+gchar *
+g_uri_unescape_string_secure (const gchar *escaped_string,
+ const gchar *illegal_characters)
+{
+ if (escaped_string == NULL)
+ return NULL;
+
+ const gchar *escaped_string_end = escaped_string + strlen (escaped_string);
+
+ gchar *result = gcry_calloc_secure (escaped_string_end - escaped_string + 1, 1);
+ gchar *out = result;
+
+ const gchar *in;
+ gint character;
+ for (in = escaped_string; in < escaped_string_end; in++) {
+ character = *in;
+
+ if (*in == '%') {
+ in++;
+ if (escaped_string_end - in < 2) {
+ // Invalid escaped char (to short)
+ gcry_free (result);
+ return NULL;
+ }
+
+ character = unescape_character (in);
+
+ // Check for an illegal character. We consider '\0' illegal here.
+ if (character <= 0 ||
+ (illegal_characters != NULL &&
+ strchr (illegal_characters, (char)character) != NULL)) {
+ gcry_free (result);
+ return NULL;
+ }
+
+ in++; // The other char will be eaten in the loop header
+ }
+ *out++ = (char)character;
+ }
+
+ *out = '\0';
+
+ return result;
+}
+
+
+guchar *
+g_base64_decode_secure (const gchar *text,
+ gsize *out_len)
+{
+ guchar *ret;
+ gsize input_length;
+ gint state = 0;
+ guint save = 0;
+
+ g_return_val_if_fail (text != NULL, NULL);
+ g_return_val_if_fail (out_len != NULL, NULL);
+
+ input_length = strlen (text);
+
+ /* We can use a smaller limit here, since we know the saved state is 0,
+ +1 used to avoid calling g_malloc0(0), and hence returning NULL */
+ ret = gcry_calloc_secure ((input_length / 4) * 3 + 1, 1);
+
+ *out_len = g_base64_decode_step (text, input_length, ret, &state, &save);
+
+ return ret;
+}
+
+
GSList *
decode_migration_data (const gchar *encoded_uri)
{
@@ -178,50 +314,58 @@
}
encoded_uri_copy += 33;
gsize out_len;
- guchar *data = g_base64_decode (g_uri_unescape_string ((encoded_uri_copy), NULL), &out_len);
+ gchar *unesc_str = g_uri_unescape_string_secure (encoded_uri_copy, NULL);
+ guchar *data = g_base64_decode_secure (unesc_str, &out_len);
+ gcry_free (unesc_str);
GSList *uris = NULL;
- gchar *uri = NULL;
+ GString *uri = NULL;
MigrationPayload *msg = migration_payload__unpack (NULL, out_len, data);
+ gcry_free (data);
for (gint i = 0; i < msg->n_otp_parameters; i++) {
- uri = g_strconcat ("otpauth://", NULL);
+ uri = g_string_new ("otpauth://");
if (msg->otp_parameters[i]->type == 1) {
- uri = g_strconcat (uri, "hotp/", NULL);
+ g_string_append (uri, "hotp/");
} else if (msg->otp_parameters[i]->type == 2) {
- uri = g_strconcat (uri, "totp/", NULL);
+ g_string_append (uri, "totp/");
} else {
g_printerr ("OTP type not recognized, skipping %s\n", msg->otp_parameters[i]->name);
goto end;
}
- uri = g_strconcat (uri, msg->otp_parameters[i]->name, "?", NULL);
+ g_string_append (uri, msg->otp_parameters[i]->name);
+ g_string_append (uri, "?");
if (msg->otp_parameters[i]->algorithm == 1) {
- uri = g_strconcat (uri, "algorithm=SHA1&", NULL);
+ g_string_append (uri, "algorithm=SHA1&");
} else if (msg->otp_parameters[i]->algorithm == 2) {
- uri = g_strconcat (uri, "algorithm=SHA256&", NULL);
+ g_string_append (uri, "algorithm=SHA256&");
} else if (msg->otp_parameters[i]->algorithm == 3) {
- uri = g_strconcat (uri, "algorithm=SHA512&", NULL);
+ g_string_append (uri, "algorithm=SHA512&");
} else {
g_printerr ("Algorithm type not supported, skipping %s\n", msg->otp_parameters[i]->name);
goto end;
}
if (msg->otp_parameters[i]->digits == 1) {
- uri = g_strconcat (uri, "digits=6&", NULL);
+ g_string_append (uri, "digits=6&");
} else if (msg->otp_parameters[i]->digits == 2) {
- uri = g_strconcat (uri, "digits=8&", NULL);
+ g_string_append (uri, "digits=8&");
} else {
g_printerr ("Algorithm type not supported, skipping %s\n", msg->otp_parameters[i]->name);
goto end;
}
if (msg->otp_parameters[i]->issuer != NULL) {
- uri = g_strconcat (uri, "issuer=", msg->otp_parameters[i]->issuer, "&", NULL);
+ g_string_append (uri, "issuer=");
+ g_string_append (uri, msg->otp_parameters[i]->issuer);
+ g_string_append (uri, "&");
}
if (msg->otp_parameters[i]->type == 1) {
- uri = g_strconcat (uri, "counter=", msg->otp_parameters[i]->counter, "&", NULL);
+ g_string_append (uri, "counter=");
+ g_string_append_printf(uri, "%ld", msg->otp_parameters[i]->counter);
+ g_string_append (uri, "&");
}
baseencode_error_t b_err;
@@ -231,56 +375,46 @@
goto end;
}
- uri = g_strconcat (uri, "secret=", b32_encoded_secret, NULL);
+ g_string_append (uri, "secret=");
+ g_string_append (uri, b32_encoded_secret);
- uris = g_slist_append (uris, g_strdup (uri));
+ uris = g_slist_append (uris, g_strdup (uri->str));
end:
- g_free (uri);
+ g_string_free (uri, TRUE);
}
+ migration_payload__free_unpacked (msg, NULL);
+
return uris;
}
-// Backported from Glib 2.68 in order to support Debian "bullseye" and Ubuntu 20.04
-guint
-g_string_replace_backported (GString *string,
- const gchar *find,
- const gchar *replace,
- guint limit)
-{
- gsize f_len, r_len, pos;
- gchar *cur, *next;
- guint n = 0;
-
- g_return_val_if_fail (string != NULL, 0);
- g_return_val_if_fail (find != NULL, 0);
- g_return_val_if_fail (replace != NULL, 0);
+gcry_cipher_hd_t
+open_cipher_and_set_data (guchar *derived_key,
+ guchar *iv,
+ gsize iv_len)
+{
+ gcry_cipher_hd_t hd;
+ gpg_error_t gpg_err = gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, GCRY_CIPHER_SECURE);
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while opening the cipher handle."));
+ return NULL;
+ }
- f_len = strlen (find);
- r_len = strlen (replace);
- cur = string->str;
+ gpg_err = gcry_cipher_setkey (hd, derived_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while setting the cipher key."));
+ gcry_cipher_close (hd);
+ return NULL;
+ }
- while ((next = strstr (cur, find)) != NULL)
- {
- pos = next - string->str;
- g_string_erase (string, pos, f_len);
- g_string_insert (string, pos, replace);
- cur = string->str + pos + r_len;
- n++;
- /* Only match the empty string once at any given position, to
- * avoid infinite loops */
- if (f_len == 0)
- {
- if (cur[0] == '\0')
- break;
- else
- cur++;
- }
- if (n == limit)
- break;
+ gpg_err = gcry_cipher_setiv (hd, iv, iv_len);
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while setting the cipher iv."));
+ gcry_cipher_close (hd);
+ return NULL;
}
- return n;
-}
+ return hd;
+}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/common/common.h new/OTPClient-3.1.1/src/common/common.h
--- old/OTPClient-3.1.0/src/common/common.h 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/common/common.h 2022-12-28 17:02:45.000000000 +0100
@@ -2,6 +2,7 @@
#include
#include
+#include
G_BEGIN_DECLS
@@ -38,4 +39,14 @@
const gchar *replace,
guint limit);
+gchar *g_uri_unescape_string_secure (const gchar *escaped_string,
+ const gchar *illegal_characters);
+
+guchar *g_base64_decode_secure (const gchar *text,
+ gsize *out_len);
+
+gcry_cipher_hd_t open_cipher_and_set_data (guchar *derived_key,
+ guchar *iv,
+ gsize iv_len);
+
G_END_DECLS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/common/freeotp.c new/OTPClient-3.1.1/src/common/freeotp.c
--- old/OTPClient-3.1.0/src/common/freeotp.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/common/freeotp.c 2022-12-28 17:02:45.000000000 +0100
@@ -11,9 +11,15 @@
GError **err)
{
GSList *otps = NULL;
- gchar *sec_buf = gcry_calloc_secure (get_file_size (path), 1);
+ goffset fs = get_file_size (path);
+ if (fs < 10) {
+ g_printerr ("Couldn't get the file size (file doesn't exit or wrong file selected\n");
+ return NULL;
+ }
+ gchar *sec_buf = gcry_calloc_secure (fs, 1);
if (!g_file_get_contents (path, &sec_buf, NULL, err)) {
g_printerr("Couldn't read into memory the freeotp txt file\n");
+ gcry_free (sec_buf);
return NULL;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/db-actions.c new/OTPClient-3.1.1/src/db-actions.c
--- old/OTPClient-3.1.0/src/db-actions.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/db-actions.c 2022-12-28 17:02:45.000000000 +0100
@@ -1,4 +1,5 @@
#include
+#include
#include "data.h"
#include "message-dialogs.h"
#include "db-actions.h"
@@ -36,8 +37,6 @@
void
update_cfg_file (AppData *app_data)
{
- GError *cfg_err = NULL;
- gchar *msg = NULL;
GKeyFile *kf = g_key_file_new ();
gchar *cfg_file_path;
#ifndef USE_FLATPAK_APP_FOLDER
@@ -45,15 +44,20 @@
#else
cfg_file_path = g_build_filename (g_get_user_data_dir (), "otpclient.cfg", NULL);
#endif
- g_key_file_load_from_file (kf, cfg_file_path, G_KEY_FILE_NONE, NULL);
+ if (!g_key_file_load_from_file (kf, cfg_file_path, G_KEY_FILE_NONE, NULL)) {
+ g_printerr ("%s\n", _("Error while loading the config file."));
+ }
g_key_file_set_string (kf, "config", "db_path", app_data->db_data->db_path);
- g_key_file_save_to_file (kf, cfg_file_path, &cfg_err);
- if (cfg_err != NULL) {
- msg = g_strconcat ("Couldn't save the change to the config file: ", &cfg_err->message, NULL);
- show_message_dialog (app_data->main_window, msg, GTK_MESSAGE_ERROR);
- g_free (msg);
- g_clear_error (&cfg_err);
+ GError *cfg_err = NULL;
+ if (!g_key_file_save_to_file (kf, cfg_file_path, &cfg_err)) {
+ if (cfg_err != NULL) {
+ gchar *msg = g_strconcat ("Couldn't save the change to the config file: ", &cfg_err->message, NULL);
+ show_message_dialog (app_data->main_window, msg, GTK_MESSAGE_ERROR);
+ g_free (msg);
+ g_clear_error (&cfg_err);
+ }
}
+
g_free (cfg_file_path);
g_key_file_free (kf);
}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/db-misc.c new/OTPClient-3.1.1/src/db-misc.c
--- old/OTPClient-3.1.0/src/db-misc.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/db-misc.c 2022-12-28 17:02:45.000000000 +0100
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include "db-misc.h"
#include "otpclient.h"
#include "file-size.h"
@@ -166,7 +167,9 @@
} else {
g_printerr ("Couldn't update the database (encrypt_db failed)\n");
if (g_file_test (db_data->db_path, G_FILE_TEST_EXISTS)) {
- g_unlink (db_data->db_path);
+ if (g_unlink (db_data->db_path) == -1) {
+ g_printerr ("%s\n", _("Error while unlinking the file."));
+ }
}
}
} else {
@@ -193,7 +196,6 @@
GError **err)
{
GError *local_err = NULL;
- gcry_cipher_hd_t hd;
HeaderData *header_data = g_new0 (HeaderData, 1);
gcry_create_nonce (header_data->iv, IV_SIZE);
@@ -224,35 +226,64 @@
gsize input_data_len = strlen (in_memory_json) + 1;
guchar *enc_buffer = g_malloc0 (input_data_len);
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0);
- gcry_cipher_setkey (hd, derived_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, header_data->iv, IV_SIZE);
- gcry_cipher_authenticate (hd, header_data, sizeof (HeaderData));
- gcry_cipher_encrypt (hd, enc_buffer, input_data_len, in_memory_json, input_data_len);
+ gcry_cipher_hd_t hd = open_cipher_and_set_data (derived_key, header_data->iv, IV_SIZE);
+ if (hd == NULL) {
+ gcry_free (derived_key);
+ g_free (header_data);
+ g_free (enc_buffer);
+ return NULL;
+ }
+
+ gpg_error_t gpg_err = gcry_cipher_authenticate (hd, header_data, sizeof (HeaderData));
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while processing the authenticated data."));
+ gcry_free (derived_key);
+ g_free (header_data);
+ g_free (enc_buffer);
+ gcry_cipher_close (hd);
+ return GENERIC_ERROR;
+ }
+ gpg_err = gcry_cipher_encrypt (hd, enc_buffer, input_data_len, in_memory_json, input_data_len);
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while encrypting the data."));
+ gcry_free (derived_key);
+ g_free (enc_buffer);
+ g_free (header_data);
+ gcry_cipher_close (hd);
+ return GENERIC_ERROR;
+ }
guchar tag[TAG_SIZE];
- gcry_cipher_gettag (hd, tag, TAG_SIZE); //append tag to outfile
+ gpg_err = gcry_cipher_gettag (hd, tag, TAG_SIZE); //append tag to outfile
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while getting the tag."));
+ gcry_free (derived_key);
+ g_free (enc_buffer);
+ g_free (header_data);
+ gcry_cipher_close (hd);
+ return GENERIC_ERROR;
+ }
if (g_output_stream_write (G_OUTPUT_STREAM(out_stream), enc_buffer, input_data_len, NULL, &local_err) == -1) {
g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Failed while writing encrypted buffer to file");
cleanup (out_file, out_stream, header_data, local_err);
- gcry_cipher_close (hd);
g_free (enc_buffer);
gcry_free (derived_key);
+ gcry_cipher_close (hd);
return GENERIC_ERROR;
}
if (g_output_stream_write (G_OUTPUT_STREAM(out_stream), tag, TAG_SIZE, NULL, &local_err) == -1) {
g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Failed while writing tag data to file");
cleanup (out_file, out_stream, header_data, local_err);
- gcry_cipher_close (hd);
g_free (enc_buffer);
gcry_free (derived_key);
+ gcry_cipher_close (hd);
return GENERIC_ERROR;
}
- gcry_cipher_close (hd);
- gcry_free (derived_key);
g_free (enc_buffer);
+ gcry_free (derived_key);
+ gcry_cipher_close (hd);
cleanup (out_file, out_stream, header_data, NULL);
return NULL;
@@ -264,7 +295,6 @@
const gchar *password)
{
GError *err = NULL;
- gcry_cipher_hd_t hd;
HeaderData *header_data = g_new0 (HeaderData, 1);
goffset input_file_size = get_file_size (db_path);
@@ -319,19 +349,49 @@
return (gpointer)derived_key;
}
- gcry_cipher_open (&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0);
- gcry_cipher_setkey (hd, derived_key, gcry_cipher_get_algo_keylen (GCRY_CIPHER_AES256));
- gcry_cipher_setiv (hd, header_data->iv, IV_SIZE);
- gcry_cipher_authenticate (hd, header_data, sizeof (HeaderData));
+ gcry_cipher_hd_t hd = open_cipher_and_set_data (derived_key, header_data->iv, IV_SIZE);
+ if (hd == NULL) {
+ gcry_free (derived_key);
+ g_free (enc_buf);
+ g_free (header_data);
+ return GENERIC_ERROR;
+ }
+
+ gpg_error_t gpg_err = gcry_cipher_authenticate (hd, header_data, sizeof (HeaderData));
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while processing the authenticated data."));
+ gcry_free (derived_key);
+ g_free (header_data);
+ g_free (enc_buf);
+ gcry_cipher_close (hd);
+ return GENERIC_ERROR;
+ }
gchar *dec_buf = gcry_calloc_secure (enc_buf_size, 1);
- gcry_cipher_decrypt (hd, dec_buf, enc_buf_size, enc_buf, enc_buf_size);
- if (gcry_err_code (gcry_cipher_checktag (hd, tag, TAG_SIZE)) == GPG_ERR_CHECKSUM) {
+ if (dec_buf == NULL) {
+ g_printerr ("%s\n", _("Error while allocating secure memory."));
+ gcry_free (derived_key);
+ g_free (header_data);
+ g_free (enc_buf);
gcry_cipher_close (hd);
+ return GENERIC_ERROR;
+ }
+ gpg_err = gcry_cipher_decrypt (hd, dec_buf, enc_buf_size, enc_buf, enc_buf_size);
+ if (gpg_err) {
+ g_printerr ("%s\n", _("Error while decrypting the data."));
gcry_free (derived_key);
+ gcry_free (dec_buf);
g_free (header_data);
g_free (enc_buf);
+ gcry_cipher_close (hd);
+ return GENERIC_ERROR;
+ }
+ if (gcry_err_code (gcry_cipher_checktag (hd, tag, TAG_SIZE)) == GPG_ERR_CHECKSUM) {
+ gcry_cipher_close (hd);
+ gcry_free (derived_key);
gcry_free (dec_buf);
+ g_free (header_data);
+ g_free (enc_buf);
return TAG_MISMATCH;
}
@@ -353,14 +413,14 @@
guchar *derived_key = gcry_malloc_secure (key_len);
if (derived_key == NULL) {
- g_printerr ("Couldn't allocate secure memory\n");
+ g_printerr ("%s\n", _("Couldn't allocate the needed secure memory."));
return SECURE_MEMORY_ALLOC_ERR;
}
gpg_error_t ret = gcry_kdf_derive (pwd, pwd_len, GCRY_KDF_PBKDF2, GCRY_MD_SHA512, header_data->salt, KDF_SALT_SIZE, KDF_ITERATIONS, key_len, derived_key);
if (ret != 0) {
gcry_free (derived_key);
- g_printerr ("Error during key derivation\n");
+ g_printerr ("%s\n", _("Error during key derivation."));
return KEY_DERIV_ERR;
}
return derived_key;
@@ -396,7 +456,7 @@
g_printerr ("Couldn't restore the backup file: %s\n", err->message);
g_clear_error (&err);
} else {
- g_print ("Backup copy successfully restored.\n");
+ g_print ("%s\n", _("Backup copy successfully restored."));
}
g_object_unref (src);
g_object_unref (dst);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/exports.c new/OTPClient-3.1.1/src/exports.c
--- old/OTPClient-3.1.0/src/exports.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/exports.c 2022-12-28 17:02:45.000000000 +0100
@@ -1,5 +1,6 @@
#include
#include
+#include
#include "password-cb.h"
#include "message-dialogs.h"
#include "common/exports.h"
@@ -54,6 +55,9 @@
}
g_free (ret_msg);
g_free (exported_file_path);
+ if (encrypted == TRUE) {
+ gcry_free (password);
+ }
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/imports.c new/OTPClient-3.1.1/src/imports.c
--- old/OTPClient-3.1.0/src/imports.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/imports.c 2022-12-28 17:02:45.000000000 +0100
@@ -120,6 +120,12 @@
}
show_message_dialog (app_data->main_window, msg, GTK_MESSAGE_ERROR);
g_free (msg_with_err);
+ if (err != NULL){
+ g_clear_error (&err);
+ }
+ if (pwd != NULL) {
+ gcry_free (pwd);
+ }
return FALSE;
}
@@ -127,6 +133,9 @@
if (err_msg != NULL) {
show_message_dialog (app_data->main_window, err_msg, GTK_MESSAGE_ERROR);
g_free (err_msg);
+ if (pwd != NULL) {
+ gcry_free (pwd);
+ }
return FALSE;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/parse-uri.c new/OTPClient-3.1.1/src/parse-uri.c
--- old/OTPClient-3.1.0/src/parse-uri.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/parse-uri.c 2022-12-28 17:02:45.000000000 +0100
@@ -74,7 +74,7 @@
gchar *escaped_label = g_uri_escape_string (constructed_label, NULL, FALSE);
g_string_append (uri, escaped_label);
g_string_append (uri, "?secret=");
- g_string_append (uri,json_string_value (json_object_get (db_obj, "secret")));
+ g_string_append (uri, json_string_value (json_object_get (db_obj, "secret")));
if (issuer != NULL && g_ascii_strcasecmp (issuer, "steam") == 0) {
g_string_append (uri, "&issuer=Steam");
}
@@ -83,27 +83,32 @@
g_string_append (uri, json_string_value (json_object_get (db_obj, "issuer")));
}
+ gchar *str_to_append = NULL;
g_string_append (uri, "&digits=");
- g_string_append (uri,g_strdup_printf ("%lld", json_integer_value ( json_object_get (db_obj, "digits"))));
+ str_to_append = g_strdup_printf ("%lld", json_integer_value ( json_object_get (db_obj, "digits")));
+ g_string_append (uri,str_to_append);
+ g_free (str_to_append);
g_string_append (uri, "&algorithm=");
g_string_append (uri, json_string_value ( json_object_get (db_obj, "algo")));
if (g_ascii_strcasecmp (json_string_value (json_object_get (db_obj, "type")), "TOTP") == 0) {
g_string_append (uri, "&period=");
- g_string_append (uri, g_strdup_printf ("%lld",json_integer_value ( json_object_get (db_obj, "period"))));
+ str_to_append = g_strdup_printf ("%lld", json_integer_value ( json_object_get (db_obj, "period")));
+ g_string_append (uri, str_to_append);
+ g_free (str_to_append);
} else {
g_string_append (uri, "&counter=");
- g_string_append (uri, g_strdup_printf ("%lld",json_integer_value ( json_object_get (db_obj, "counter"))));
+ str_to_append = g_strdup_printf ("%lld", json_integer_value ( json_object_get (db_obj, "counter")));
+ g_string_append (uri, str_to_append);
+ g_free (str_to_append);
}
g_string_append (uri, "\n");
- gchar *ret_uri = g_strdup (uri->str);
g_free (constructed_label);
g_free (escaped_label);
- g_string_free (uri, TRUE);
- return ret_uri;
+ return g_string_free (uri, FALSE);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/qrcode-parser.c new/OTPClient-3.1.1/src/qrcode-parser.c
--- old/OTPClient-3.1.0/src/qrcode-parser.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/qrcode-parser.c 2022-12-28 17:02:45.000000000 +0100
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include "common/common.h"
typedef struct image_data_t {
@@ -46,7 +47,9 @@
const zbar_symbol_t *symbol = zbar_image_first_symbol (image);
for (; symbol; symbol = zbar_symbol_next (symbol)) {
- *otpauth_uri = secure_strdup (g_uri_unescape_string (zbar_symbol_get_data (symbol), NULL));
+ gchar *unesc_str = g_uri_unescape_string_secure (zbar_symbol_get_data (symbol), NULL);
+ *otpauth_uri = secure_strdup (unesc_str);
+ gcry_free (unesc_str);
}
zbar_image_destroy (image);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/settings-cb.c new/OTPClient-3.1.1/src/settings-cb.c
--- old/OTPClient-3.1.0/src/settings-cb.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/settings-cb.c 2022-12-28 17:02:45.000000000 +0100
@@ -1,4 +1,5 @@
#include
+#include
#include "otpclient.h"
#include "message-dialogs.h"
#include "get-builder.h"
@@ -24,6 +25,7 @@
g_free (msg);
g_free (cfg_file_path);
g_key_file_free (kf);
+ g_clear_error (&err);
return;
}
@@ -79,7 +81,9 @@
g_key_file_set_integer (kf, "config", "inactivity_timeout", app_data->inactivity_timeout);
g_key_file_set_boolean (kf, "config", "dark_theme", app_data->use_dark_theme);
g_key_file_set_boolean (kf, "config", "disable_secret_service", app_data->disable_secret_service);
- g_key_file_save_to_file (kf, cfg_file_path, NULL);
+ if (!g_key_file_save_to_file (kf, cfg_file_path, NULL)) {
+ g_printerr ("%s\n", _("Error while saving the config file."));
+ }
gtk_tree_view_set_search_column (GTK_TREE_VIEW(app_data->tree_view), app_data->search_column + 1);
break;
case GTK_RESPONSE_CANCEL:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/show-qr-cb.c new/OTPClient-3.1.1/src/show-qr-cb.c
--- old/OTPClient-3.1.0/src/show-qr-cb.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/show-qr-cb.c 2022-12-28 17:02:45.000000000 +0100
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include "data.h"
#include "parse-uri.h"
#include "get-builder.h"
@@ -45,7 +46,9 @@
gtk_widget_destroy (diag);
g_object_unref (pbuf);
g_object_unref (builder);
- g_unlink (PNG_OUT);
+ if (g_unlink (PNG_OUT) == -1) {
+ g_printerr ("%s\n", _("Couldn't unlink the PNG file."));
+ }
}
}
@@ -62,40 +65,37 @@
write_png (const QRcode *qrcode)
{
guint realwidth = (qrcode->width + MARGIN * 2) * SIZE;
- guchar *row = (guchar *)malloc ((size_t)((realwidth + 7) / 8));
+ guchar *row = (guchar *)g_malloc0 ((size_t)((realwidth + 7) / 8));
if (row == NULL) {
g_printerr ("Failed to allocate memory.\n");
return -1;
}
- FILE *fp = fopen (PNG_OUT, "wb");
- if (fp == NULL) {
- g_printerr ("Failed to create file: %s\n", PNG_OUT);
- perror(NULL);
- return -1;
- }
-
png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
g_printerr ("Failed to initialize PNG writer.\n");
+ g_free (row);
return -1;
}
png_infop info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) {
g_printerr ("Failed to initialize PNG write.\n");
+ g_free (row);
return -1;
}
if (setjmp (png_jmpbuf(png_ptr))) {
png_destroy_write_struct (&png_ptr, &info_ptr);
g_printerr ("Failed to write PNG image.\n");
+ g_free (row);
return -1;
}
- png_colorp palette = (png_colorp)malloc(sizeof (png_color) * 2);
+ png_colorp palette = (png_colorp)g_malloc0 (sizeof (png_color) * 2);
if (palette == NULL) {
g_printerr ("Failed to allocate memory.\n");
+ g_free (row);
return -1;
}
@@ -114,6 +114,12 @@
png_set_PLTE(png_ptr, info_ptr, palette, 2);
png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL);
+ FILE *fp = fopen (PNG_OUT, "wb");
+ if (fp == NULL) {
+ g_printerr ("Failed to create file: %s\n", PNG_OUT);
+ g_free (row);
+ return -1;
+ }
png_init_io (png_ptr, fp);
png_set_IHDR (png_ptr, info_ptr,
(guint)realwidth, (guint)realwidth,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.1.0/src/webcam-add-cb.c new/OTPClient-3.1.1/src/webcam-add-cb.c
--- old/OTPClient-3.1.0/src/webcam-add-cb.c 2022-12-19 14:16:00.000000000 +0100
+++ new/OTPClient-3.1.1/src/webcam-add-cb.c 2022-12-28 17:02:45.000000000 +0100
@@ -111,7 +111,9 @@
ConfigData *cfg_data = (ConfigData *)user_data;
const zbar_symbol_t *symbol = zbar_image_first_symbol (image);
for (; symbol; symbol = zbar_symbol_next (symbol)) {
- cfg_data->otp_uri = secure_strdup (g_uri_unescape_string (zbar_symbol_get_data (symbol), NULL));
+ gchar *unesc_str = g_uri_unescape_string_secure (zbar_symbol_get_data (symbol), NULL);
+ cfg_data->otp_uri = secure_strdup (unesc_str);
cfg_data->qrcode_found = TRUE;
+ gcry_free (unesc_str);
}
}