aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2023-12-03 07:28:41 +0000
committersaturneric <[email protected]>2023-12-03 07:28:41 +0000
commite0bc882bd46c40c86d9497fa043bbfe3e469888f (patch)
tree962b673899e4209ddd3504e975dcbac6758c496e
parentfeat: add buddled qt pinentry and make it works (diff)
downloadGpgFrontend-e0bc882bd46c40c86d9497fa043bbfe3e469888f.tar.gz
GpgFrontend-e0bc882bd46c40c86d9497fa043bbfe3e469888f.zip
feat: introduce mimalloc to replace secmem
Diffstat (limited to '')
-rw-r--r--.gitmodules5
-rw-r--r--CMakeLists.txt2
-rw-r--r--gpgfrontend.qrc5
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/GpgFrontendCore.cpp32
-rw-r--r--src/core/GpgFrontendCore.h1
-rw-r--r--src/core/function/gpg/GpgContext.cpp13
-rw-r--r--src/core/function/gpg/GpgKeyOpera.cpp3
-rw-r--r--src/core/function/secure_memory/SecureMemoryAllocator.cpp44
-rw-r--r--src/core/function/secure_memory/SecureMemoryAllocator.h44
-rw-r--r--src/core/utils/MemoryUtils.cpp42
-rw-r--r--src/core/utils/MemoryUtils.h172
-rw-r--r--src/pinentry/CMakeLists.txt7
-rw-r--r--src/pinentry/argparse.cpp1360
-rw-r--r--src/pinentry/argparse.h204
-rw-r--r--src/pinentry/capslock/capslock.cpp4
-rw-r--r--src/pinentry/password_cache.cpp153
-rw-r--r--src/pinentry/password_cache.h30
-rw-r--r--src/pinentry/pinentry.cpp711
-rw-r--r--src/pinentry/pinentry.h22
-rw-r--r--src/pinentry/pinentry_main.cpp413
-rw-r--r--src/pinentry/pinentrydialog.cpp11
-rw-r--r--src/pinentry/pinentrydialog.h4
-rw-r--r--src/pinentry/pinlineedit.h50
-rw-r--r--src/pinentry/secmem.cpp375
-rw-r--r--src/pinentry/secmem.h55
-rw-r--r--src/pinentry/secmem_util.h65
-rw-r--r--src/ui/CMakeLists.txt7
-rw-r--r--src/ui/UserInterfaceUtils.cpp1
-rw-r--r--src/ui/function/RaisePinentry.cpp84
-rw-r--r--src/ui/function/RaisePinentry.h42
-rw-r--r--src/ui/function/SetOwnerTrustLevel.h1
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp50
-rw-r--r--third_party/CMakeLists.txt5
m---------third_party/mimalloc0
35 files changed, 545 insertions, 3478 deletions
diff --git a/.gitmodules b/.gitmodules
index 397da182..3463984f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -6,4 +6,7 @@
url = https://github.com/bricke/Qt-AES.git
[submodule "third_party/spdlog"]
path = third_party/spdlog
- url = https://github.com/gabime/spdlog.git \ No newline at end of file
+ url = https://github.com/gabime/spdlog.git
+[submodule "third_party/mimalloc"]
+ path = third_party/mimalloc
+ url = https://github.com/microsoft/mimalloc.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d164dc9d..5fd05f30 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -346,7 +346,7 @@ if (LINUX)
endif()
if(USING_COMPILER_CLANG)
- add_compile_options(-stdlib=libstdc++)
+ add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-stdlib=libstdc++>)
endif()
if(SYSTEM_NAME STREQUAL "FreeBSD")
diff --git a/gpgfrontend.qrc b/gpgfrontend.qrc
index 59859444..eb85ee76 100644
--- a/gpgfrontend.qrc
+++ b/gpgfrontend.qrc
@@ -75,5 +75,10 @@
<file alias="button_next.png">resource/lfs/icons/button_next.png</file>
<file alias="refresh.png">resource/lfs/icons/refresh.png</file>
<file alias="up.png">resource/lfs/icons/up.png</file>
+ <file alias="data-error.svg">resource/lfs/icons/data-error.svg</file>
+ <file alias="document-encrypt.png">resource/lfs/icons/document-encrypt.png</file>
+ <file alias="hint.svg">resource/lfs/icons/hint.svg</file>
+ <file alias="password-generate.svg">resource/lfs/icons/password-generate.svg</file>
+ <file alias="visibility.svg">resource/lfs/icons/visibility.svg</file>
</qresource>
</RCC>
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 137acc7b..ebc08df5 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -27,6 +27,7 @@
aux_source_directory(./function/result_analyse CORE_SOURCE)
aux_source_directory(./function/basic CORE_SOURCE)
aux_source_directory(./function/gpg CORE_SOURCE)
+aux_source_directory(./function/secure_memory CORE_SOURCE)
aux_source_directory(./function CORE_SOURCE)
aux_source_directory(./thread CORE_SOURCE)
aux_source_directory(./model CORE_SOURCE)
@@ -43,8 +44,7 @@ add_library(gpgfrontend_core SHARED ${CORE_SOURCE})
set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendCoreExport.h")
generate_export_header(gpgfrontend_core EXPORT_FILE_NAME "${_export_file}")
-# link buddled pinentry
-target_link_libraries(gpgfrontend_core PRIVATE gpgfrontend_pinentry)
+target_link_libraries(gpgfrontend_core PUBLIC mimalloc)
# link third-party libraries
target_link_libraries(gpgfrontend_core PUBLIC config++)
@@ -83,7 +83,7 @@ if (MINGW)
endif ()
# spdlog
-target_link_libraries(gpgfrontend_core PRIVATE spdlog)
+target_link_libraries(gpgfrontend_core PUBLIC spdlog)
# link libarchive
if(APPLE)
diff --git a/src/core/GpgFrontendCore.cpp b/src/core/GpgFrontendCore.cpp
new file mode 100644
index 00000000..5021b37d
--- /dev/null
+++ b/src/core/GpgFrontendCore.cpp
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "core/GpgFrontendCore.h"
+
+// mimalloc
+#include <mimalloc-new-delete.h> \ No newline at end of file
diff --git a/src/core/GpgFrontendCore.h b/src/core/GpgFrontendCore.h
index fcf890fa..89f2dee6 100644
--- a/src/core/GpgFrontendCore.h
+++ b/src/core/GpgFrontendCore.h
@@ -32,6 +32,7 @@
#include <QtCore>
// std
+#include <cstdint>
#include <filesystem>
#include <memory>
#include <string>
diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp
index 9ee81bad..a6040231 100644
--- a/src/core/function/gpg/GpgContext.cpp
+++ b/src/core/function/gpg/GpgContext.cpp
@@ -30,18 +30,6 @@
#include <gpg-error.h>
#include <gpgme.h>
-#include <qapplication.h>
-#include <qcoreapplication.h>
-#include <qeasingcurve.h>
-#include <qeventloop.h>
-#include <qlabel.h>
-#include <qobject.h>
-#include <qtmetamacros.h>
-#include <qwindowdefs.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cstring>
#include "core/function/CoreSignalStation.h"
#include "core/function/basic/GpgFunctionObject.h"
@@ -54,7 +42,6 @@
#include "core/utils/CommonUtils.h"
#include "core/utils/GpgUtils.h"
#include "function/CacheManager.h"
-#include "spdlog/spdlog.h"
#ifdef _WIN32
#include <windows.h>
diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp
index 64f33373..751d4f51 100644
--- a/src/core/function/gpg/GpgKeyOpera.cpp
+++ b/src/core/function/gpg/GpgKeyOpera.cpp
@@ -49,7 +49,6 @@
#include "core/utils/CommonUtils.h"
#include "core/utils/GpgUtils.h"
#include "model/DataObject.h"
-#include "spdlog/spdlog.h"
namespace GpgFrontend {
@@ -290,7 +289,7 @@ void GpgKeyOpera::ModifyPassword(const GpgKey& key,
return;
}
- auto *task = new Thread::Task(
+ auto* task = new Thread::Task(
[&](const DataObjectPtr& data_object) -> int {
auto err = gpgme_op_passwd(ctx_, static_cast<gpgme_key_t>(key), 0);
data_object->Swap({err});
diff --git a/src/core/function/secure_memory/SecureMemoryAllocator.cpp b/src/core/function/secure_memory/SecureMemoryAllocator.cpp
new file mode 100644
index 00000000..09390305
--- /dev/null
+++ b/src/core/function/secure_memory/SecureMemoryAllocator.cpp
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "SecureMemoryAllocator.h"
+
+#include <mimalloc.h>
+
+namespace GpgFrontend {
+
+auto SecurityMemoryAllocator::Allocate(std::size_t size) -> void* {
+ return mi_malloc(size);
+}
+
+auto SecurityMemoryAllocator::Reallocate(void* ptr, std::size_t size) -> void* {
+ return mi_realloc(ptr, size);
+}
+
+void SecurityMemoryAllocator::Deallocate(void* p) { mi_free(p); }
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/function/secure_memory/SecureMemoryAllocator.h b/src/core/function/secure_memory/SecureMemoryAllocator.h
new file mode 100644
index 00000000..724da226
--- /dev/null
+++ b/src/core/function/secure_memory/SecureMemoryAllocator.h
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+#include <cstdint>
+
+namespace GpgFrontend {
+
+class GPGFRONTEND_CORE_EXPORT SecurityMemoryAllocator {
+ public:
+ static auto Allocate(std::size_t) -> void*;
+
+ static auto Reallocate(void*, std::size_t) -> void*;
+
+ static void Deallocate(void*);
+};
+
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/utils/MemoryUtils.cpp b/src/core/utils/MemoryUtils.cpp
new file mode 100644
index 00000000..eae9fa10
--- /dev/null
+++ b/src/core/utils/MemoryUtils.cpp
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "MemoryUtils.h"
+
+namespace GpgFrontend {
+
+auto SecureMalloc(std::size_t size) -> void * {
+ return SecurityMemoryAllocator::Allocate(size);
+}
+
+auto SecureRealloc(void *ptr, std::size_t size) -> void * {
+ return SecurityMemoryAllocator::Reallocate(ptr, size);
+}
+
+void SecureFree(void *ptr) { SecurityMemoryAllocator::Deallocate(ptr); }
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/utils/MemoryUtils.h b/src/core/utils/MemoryUtils.h
new file mode 100644
index 00000000..507f693f
--- /dev/null
+++ b/src/core/utils/MemoryUtils.h
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+#include "core/GpgFrontendCoreExport.h"
+#include "core/function/secure_memory/SecureMemoryAllocator.h"
+
+/* To avoid that a compiler optimizes certain memset calls away, these
+ macros may be used instead. */
+#define wipememory2(_ptr, _set, _len) \
+ do { \
+ volatile char *_vptr = (volatile char *)(_ptr); \
+ size_t _vlen = (_len); \
+ while (_vlen) { \
+ *_vptr = (_set); \
+ _vptr++; \
+ _vlen--; \
+ } \
+ } while (0)
+#define wipememory(_ptr, _len) wipememory2(_ptr, 0, _len)
+#define wipe(_ptr, _len) wipememory2(_ptr, 0, _len)
+
+#define xtoi_1(p) \
+ (*(p) <= '9' ? (*(p) - '0') \
+ : *(p) <= 'F' ? (*(p) - 'A' + 10) \
+ : (*(p) - 'a' + 10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p) + 1))
+
+namespace GpgFrontend {
+
+template <typename T>
+class PointerConverter {
+ public:
+ explicit PointerConverter(void *ptr) : ptr_(ptr) {}
+
+ auto AsType() const -> T * { return static_cast<T *>(ptr_); }
+
+ private:
+ void *ptr_;
+};
+
+/**
+ * @brief
+ *
+ * @return void*
+ */
+auto GPGFRONTEND_CORE_EXPORT SecureMalloc(std::size_t) -> void *;
+
+/**
+ * @brief
+ *
+ * @return void*
+ */
+auto GPGFRONTEND_CORE_EXPORT SecureRealloc(void *, std::size_t) -> void *;
+
+/**
+ * @brief
+ *
+ * @tparam T
+ * @return T*
+ */
+template <typename T>
+auto SecureMallocAsType(std::size_t size) -> T * {
+ return PointerConverter<T>(SecurityMemoryAllocator::Allocate(size)).AsType();
+}
+
+/**
+ * @brief
+ *
+ * @return void*
+ */
+template <typename T>
+auto SecureReallocAsType(T *ptr, std::size_t size) -> T * {
+ return PointerConverter<T>(SecurityMemoryAllocator::Reallocate(ptr, size))
+ .AsType();
+}
+
+/**
+ * @brief
+ *
+ */
+void GPGFRONTEND_CORE_EXPORT SecureFree(void *);
+
+template <typename T>
+struct SecureObjectDeleter {
+ void operator()(T *ptr) {
+ if (ptr) {
+ ptr->~T();
+ SecurityMemoryAllocator::Deallocate(ptr);
+ }
+ }
+};
+
+template <typename T, typename... Args>
+static auto SecureCreateObject(Args &&...args) -> T * {
+ void *mem = SecurityMemoryAllocator::Allocate(sizeof(T));
+ if (!mem) return nullptr;
+
+ try {
+ return new (mem) T(std::forward<Args>(args)...);
+ } catch (...) {
+ SecurityMemoryAllocator::Deallocate(mem);
+ throw;
+ }
+}
+
+template <typename T>
+static void SecureDestroyObject(T *obj) {
+ if (!obj) return;
+ obj->~T();
+ SecurityMemoryAllocator::Deallocate(obj);
+}
+
+template <typename T, typename... Args>
+static auto SecureCreateUniqueObject(Args &&...args)
+ -> std::unique_ptr<T, SecureObjectDeleter<T>> {
+ void *mem = SecurityMemoryAllocator::Allocate(sizeof(T));
+ if (!mem) throw std::bad_alloc();
+
+ try {
+ return std::unique_ptr<T, SecureObjectDeleter<T>>(
+ new (mem) T(std::forward<Args>(args)...));
+ } catch (...) {
+ SecurityMemoryAllocator::Deallocate(mem);
+ throw;
+ }
+}
+
+template <typename T, typename... Args>
+auto SecureCreateSharedObject(Args &&...args) -> std::shared_ptr<T> {
+ void *mem = SecurityMemoryAllocator::Allocate(sizeof(T));
+ if (!mem) throw std::bad_alloc();
+
+ try {
+ T *obj = new (mem) T(std::forward<Args>(args)...);
+ return std::shared_ptr<T>(obj, [](T *ptr) {
+ ptr->~T();
+ SecurityMemoryAllocator::Deallocate(ptr);
+ });
+ } catch (...) {
+ SecurityMemoryAllocator::Deallocate(mem);
+ throw;
+ }
+}
+
+}; // namespace GpgFrontend \ No newline at end of file
diff --git a/src/pinentry/CMakeLists.txt b/src/pinentry/CMakeLists.txt
index e6d53feb..b5283d11 100644
--- a/src/pinentry/CMakeLists.txt
+++ b/src/pinentry/CMakeLists.txt
@@ -33,14 +33,15 @@ else()
list(APPEND PINENTRY_SOURCE "capslock/capslock_unix.cpp")
endif()
-message(STATUS "PINENTRY_SOURCE: ${PINENTRY_SOURCE}")
add_library(gpgfrontend_pinentry SHARED ${PINENTRY_SOURCE})
+target_link_libraries(gpgfrontend_pinentry PUBLIC gpgfrontend_core)
+
# link Qt core
if(Qt6_DIR)
- target_link_libraries(gpgfrontend_pinentry PUBLIC Qt6::Core Qt6::Widgets)
+ target_link_libraries(gpgfrontend_pinentry PUBLIC Qt6::Widgets)
else()
- target_link_libraries(gpgfrontend_pinentry PUBLIC Qt5::Core Qt5::Widgets)
+ target_link_libraries(gpgfrontend_pinentry PUBLIC Qt5::Widgets)
endif()
# using std c++ 17
diff --git a/src/pinentry/argparse.cpp b/src/pinentry/argparse.cpp
deleted file mode 100644
index d3568c64..00000000
--- a/src/pinentry/argparse.cpp
+++ /dev/null
@@ -1,1360 +0,0 @@
-/* [argparse.c wk 17.06.97] Argument Parser for option handling
- * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
- * Copyright (C) 1997-2001, 2006-2008, 2013-2015 Werner Koch
- *
- * This file is part of JNLIB, which is a subsystem of GnuPG.
- *
- * JNLIB is free software; you can redistribute it and/or modify it
- * under the terms of either
- *
- * - the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at
- * your option) any later version.
- *
- * or
- *
- * - the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * or both in parallel, as here.
- *
- * JNLIB is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copies of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, see <https://www.gnu.org/licenses/>.
- * SPDX-License-Identifier: (GPL-2.0+ OR LGPL-3.0+)
- */
-
-/* This file may be used as part of GnuPG or standalone. A GnuPG
- build is detected by the presence of the macro GNUPG_MAJOR_VERSION.
- Some feature are only availalbe in the GnuPG build mode.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef GNUPG_MAJOR_VERSION
-#include "libjnlib-config.h"
-#include "logging.h"
-#include "mischelp.h"
-#include "stringhelp.h"
-#ifdef JNLIB_NEED_UTF8CONV
-#include "utf8conv.h"
-#endif
-#endif /*GNUPG_MAJOR_VERSION*/
-
-#include "argparse.h"
-
-/* GnuPG uses GPLv3+ but a standalone version of this defaults to
- GPLv2+ because that is the license of this file. Change this if
- you include it in a program which uses GPLv3. If you don't want to
- set a a copyright string for your usage() you may also hardcode it
- here. */
-#ifndef GNUPG_MAJOR_VERSION
-
-#define ARGPARSE_GPL_VERSION 2
-#define ARGPARSE_CRIGHT_STR "Copyright (C) YEAR NAME"
-
-#else /* Used by GnuPG */
-
-#define ARGPARSE_GPL_VERSION 3
-#define ARGPARSE_CRIGHT_STR "Copyright (C) 2015 Free Software Foundation, Inc."
-
-#endif /*GNUPG_MAJOR_VERSION*/
-
-/* Replacements for standalone builds. */
-#ifndef GNUPG_MAJOR_VERSION
-#ifndef _
-#define _(a) (a)
-#endif
-#ifndef DIM
-#define DIM(v) (sizeof(v) / sizeof((v)[0]))
-#endif
-#define jnlib_malloc(a) malloc((a))
-#define jnlib_realloc(a, b) realloc((a), (b))
-#define jnlib_strdup(a) strdup((a))
-#define jnlib_free(a) free((a))
-#define jnlib_log_error my_log_error
-#define jnlib_log_bug my_log_bug
-#define trim_spaces(a) my_trim_spaces((a))
-#define map_static_macro_string(a) (a)
-#endif /*!GNUPG_MAJOR_VERSION*/
-
-#define ARGPARSE_STR(v) #v
-#define ARGPARSE_STR2(v) ARGPARSE_STR(v)
-
-/* Replacements for standalone builds. */
-#ifndef GNUPG_MAJOR_VERSION
-static void my_log_error(const char *fmt, ...) {
- va_list arg_ptr;
-
- va_start(arg_ptr, fmt);
- fprintf(stderr, "%s: ", strusage(11));
- vfprintf(stderr, fmt, arg_ptr);
- va_end(arg_ptr);
-}
-
-static void my_log_bug(const char *fmt, ...) {
- va_list arg_ptr;
-
- va_start(arg_ptr, fmt);
- fprintf(stderr, "%s: Ohhhh jeeee: ", strusage(11));
- vfprintf(stderr, fmt, arg_ptr);
- va_end(arg_ptr);
- abort();
-}
-
-static char *my_trim_spaces(char *str) {
- char *string, *p, *mark;
-
- string = str;
- /* Find first non space character. */
- for (p = string; *p && isspace(*(unsigned char *)p); p++)
- ;
- /* Move characters. */
- for ((mark = NULL); (*string = *p); string++, p++)
- if (isspace(*(unsigned char *)p)) {
- if (!mark) mark = string;
- } else
- mark = NULL;
- if (mark) *mark = '\0'; /* Remove trailing spaces. */
-
- return str;
-}
-
-#endif /*!GNUPG_MAJOR_VERSION*/
-
-/*********************************
- * @Summary arg_parse
- * #include "argparse.h"
- *
- * typedef struct {
- * char *argc; pointer to argc (value subject to change)
- * char ***argv; pointer to argv (value subject to change)
- * unsigned flags; Global flags (DO NOT CHANGE)
- * int err; print error about last option
- * 1 = warning, 2 = abort
- * int r_opt; return option
- * int r_type; type of return value (0 = no argument found)
- * union {
- * int ret_int;
- * long ret_long
- * ulong ret_ulong;
- * char *ret_str;
- * } r; Return values
- * struct {
- * int idx;
- * const char *last;
- * void *aliases;
- * } internal; DO NOT CHANGE
- * } ARGPARSE_ARGS;
- *
- * typedef struct {
- * int short_opt;
- * const char *long_opt;
- * unsigned flags;
- * } ARGPARSE_OPTS;
- *
- * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
- *
- * @Description
- * This is my replacement for getopt(). See the example for a typical usage.
- * Global flags are:
- * Bit 0 : Do not remove options form argv
- * Bit 1 : Do not stop at last option but return other args
- * with r_opt set to -1.
- * Bit 2 : Assume options and real args are mixed.
- * Bit 3 : Do not use -- to stop option processing.
- * Bit 4 : Do not skip the first arg.
- * Bit 5 : allow usage of long option with only one dash
- * Bit 6 : ignore --version
- * all other bits must be set to zero, this value is modified by the
- * function, so assume this is write only.
- * Local flags (for each option):
- * Bit 2-0 : 0 = does not take an argument
- * 1 = takes int argument
- * 2 = takes string argument
- * 3 = takes long argument
- * 4 = takes ulong argument
- * Bit 3 : argument is optional (r_type will the be set to 0)
- * Bit 4 : allow 0x etc. prefixed values.
- * Bit 6 : Ignore this option
- * Bit 7 : This is a command and not an option
- * You stop the option processing by setting opts to NULL, the function will
- * then return 0.
- * @Return Value
- * Returns the args.r_opt or 0 if ready
- * r_opt may be -2/-7 to indicate an unknown option/command.
- * @See Also
- * ArgExpand
- * @Notes
- * You do not need to process the options 'h', '--help' or '--version'
- * because this function includes standard help processing; but if you
- * specify '-h', '--help' or '--version' you have to do it yourself.
- * The option '--' stops argument processing; if bit 1 is set the function
- * continues to return normal arguments.
- * To process float args or unsigned args you must use a string args and do
- * the conversion yourself.
- * @Example
- *
- * ARGPARSE_OPTS opts[] = {
- * { 'v', "verbose", 0 },
- * { 'd', "debug", 0 },
- * { 'o', "output", 2 },
- * { 'c', "cross-ref", 2|8 },
- * { 'm', "my-option", 1|8 },
- * { 300, "ignored-long-option, ARGPARSE_OP_IGNORE},
- * { 500, "have-no-short-option-for-this-long-option", 0 },
- * {0} };
- * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
- *
- * while( ArgParse( &pargs, &opts) ) {
- * switch( pargs.r_opt ) {
- * case 'v': opt.verbose++; break;
- * case 'd': opt.debug++; break;
- * case 'o': opt.outfile = pargs.r.ret_str; break;
- * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
- * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
- * case 500: opt.a_long_one++; break
- * default : pargs.err = 1; break; -- force warning output --
- * }
- * }
- * if( argc > 1 )
- * log_fatal( "Too many args");
- *
- */
-
-typedef struct alias_def_s *ALIAS_DEF;
-struct alias_def_s {
- ALIAS_DEF next;
- char *name; /* malloced buffer with name, \0, value */
- const char *value; /* ptr into name */
-};
-
-/* Object to store the names for the --ignore-invalid-option option.
- This is a simple linked list. */
-typedef struct iio_item_def_s *IIO_ITEM_DEF;
-struct iio_item_def_s {
- IIO_ITEM_DEF next;
- char name[1]; /* String with the long option name. */
-};
-
-static const char *(*strusage_handler)(int) = NULL;
-static int (*custom_outfnc)(int, const char *);
-
-static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
-static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
-static void show_version(void);
-static int writestrings(int is_error, const char *string, ...)
-#if __GNUC__ >= 4
- __attribute__((sentinel(0)))
-#endif
- ;
-
-void argparse_register_outfnc(int (*fnc)(int, const char *)) {
- custom_outfnc = fnc;
-}
-
-/* Write STRING and all following const char * arguments either to
- stdout or, if IS_ERROR is set, to stderr. The list of strings must
- be terminated by a NULL. */
-static int writestrings(int is_error, const char *string, ...) {
- va_list arg_ptr;
- const char *s;
- int count = 0;
-
- if (string) {
- s = string;
- va_start(arg_ptr, string);
- do {
- if (custom_outfnc)
- custom_outfnc(is_error ? 2 : 1, s);
- else
- fputs(s, is_error ? stderr : stdout);
- count += strlen(s);
- } while ((s = va_arg(arg_ptr, const char *)));
- va_end(arg_ptr);
- }
- return count;
-}
-
-static void flushstrings(int is_error) {
- if (custom_outfnc)
- custom_outfnc(is_error ? 2 : 1, NULL);
- else
- fflush(is_error ? stderr : stdout);
-}
-
-static void initialize(ARGPARSE_ARGS *arg, const char *filename,
- unsigned *lineno) {
- if (!(arg->flags & (1 << 15))) {
- /* Initialize this instance. */
- arg->internal.idx = 0;
- arg->internal.last = NULL;
- arg->internal.inarg = 0;
- arg->internal.stopped = 0;
- arg->internal.aliases = NULL;
- arg->internal.cur_alias = NULL;
- arg->internal.iio_list = NULL;
- arg->err = 0;
- arg->flags |= 1 << 15; /* Mark as initialized. */
- if (*arg->argc < 0) jnlib_log_bug("invalid argument for arg_parse\n");
- }
-
- if (arg->err) {
- /* Last option was erroneous. */
- const char *s;
-
- if (filename) {
- if (arg->r_opt == ARGPARSE_UNEXPECTED_ARG)
- s = _("argument not expected");
- else if (arg->r_opt == ARGPARSE_READ_ERROR)
- s = _("read error");
- else if (arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG)
- s = _("keyword too long");
- else if (arg->r_opt == ARGPARSE_MISSING_ARG)
- s = _("missing argument");
- else if (arg->r_opt == ARGPARSE_INVALID_ARG)
- s = _("invalid argument");
- else if (arg->r_opt == ARGPARSE_INVALID_COMMAND)
- s = _("invalid command");
- else if (arg->r_opt == ARGPARSE_INVALID_ALIAS)
- s = _("invalid alias definition");
- else if (arg->r_opt == ARGPARSE_OUT_OF_CORE)
- s = _("out of core");
- else
- s = _("invalid option");
- jnlib_log_error("%s:%u: %s\n", filename, *lineno, s);
- } else {
- s = arg->internal.last ? arg->internal.last : "[??]";
-
- if (arg->r_opt == ARGPARSE_MISSING_ARG)
- jnlib_log_error(_("missing argument for option \"%.50s\"\n"), s);
- else if (arg->r_opt == ARGPARSE_INVALID_ARG)
- jnlib_log_error(_("invalid argument for option \"%.50s\"\n"), s);
- else if (arg->r_opt == ARGPARSE_UNEXPECTED_ARG)
- jnlib_log_error(_("option \"%.50s\" does not expect an "
- "argument\n"),
- s);
- else if (arg->r_opt == ARGPARSE_INVALID_COMMAND)
- jnlib_log_error(_("invalid command \"%.50s\"\n"), s);
- else if (arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION)
- jnlib_log_error(_("option \"%.50s\" is ambiguous\n"), s);
- else if (arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND)
- jnlib_log_error(_("command \"%.50s\" is ambiguous\n"), s);
- else if (arg->r_opt == ARGPARSE_OUT_OF_CORE)
- jnlib_log_error("%s\n", _("out of core\n"));
- else
- jnlib_log_error(_("invalid option \"%.50s\"\n"), s);
- }
- if (arg->err != ARGPARSE_PRINT_WARNING) exit(2);
- arg->err = 0;
- }
-
- /* Zero out the return value union. */
- arg->r.ret_str = NULL;
- arg->r.ret_long = 0;
-}
-
-static void store_alias(ARGPARSE_ARGS *arg, char *name, char *value) {
- /* TODO: replace this dummy function with a rea one
- * and fix the probelms IRIX has with (ALIAS_DEV)arg..
- * used as lvalue
- */
- (void)arg;
- (void)name;
- (void)value;
-#if 0
- ALIAS_DEF a = jnlib_xmalloc( sizeof *a );
- a->name = name;
- a->value = value;
- a->next = (ALIAS_DEF)arg->internal.aliases;
- (ALIAS_DEF)arg->internal.aliases = a;
-#endif
-}
-
-/* Return true if KEYWORD is in the ignore-invalid-option list. */
-static int ignore_invalid_option_p(ARGPARSE_ARGS *arg, const char *keyword) {
- IIO_ITEM_DEF item = (IIO_ITEM_DEF)arg->internal.iio_list;
-
- for (; item; item = item->next)
- if (!strcmp(item->name, keyword)) return 1;
- return 0;
-}
-
-/* Add the keywords up to the next LF to the list of to be ignored
- options. After returning FP will either be at EOF or the next
- character read wll be the first of a new line. The function
- returns 0 on success or true on malloc failure. */
-static int ignore_invalid_option_add(ARGPARSE_ARGS *arg, FILE *fp) {
- IIO_ITEM_DEF item;
- int c;
- char name[100];
- int namelen = 0;
- int ready = 0;
- enum { skipWS, collectNAME, skipNAME, addNAME } state = skipWS;
-
- while (!ready) {
- c = getc(fp);
- if (c == '\n')
- ready = 1;
- else if (c == EOF) {
- c = '\n';
- ready = 1;
- }
- again:
- switch (state) {
- case skipWS:
- if (!isascii(c) || !isspace(c)) {
- namelen = 0;
- state = collectNAME;
- goto again;
- }
- break;
-
- case collectNAME:
- if (isspace(c)) {
- state = addNAME;
- goto again;
- } else if (namelen < DIM(name) - 1)
- name[namelen++] = c;
- else /* Too long. */
- state = skipNAME;
- break;
-
- case skipNAME:
- if (isspace(c)) {
- state = skipWS;
- goto again;
- }
- break;
-
- case addNAME:
- name[namelen] = 0;
- if (!ignore_invalid_option_p(arg, name)) {
- item = (IIO_ITEM_DEF)jnlib_malloc(sizeof *item + namelen);
- if (!item) return 1;
- strcpy(item->name, name);
- item->next = (IIO_ITEM_DEF)arg->internal.iio_list;
- arg->internal.iio_list = item;
- }
- state = skipWS;
- goto again;
- }
- }
- return 0;
-}
-
-/* Clear the entire ignore-invalid-option list. */
-static void ignore_invalid_option_clear(ARGPARSE_ARGS *arg) {
- IIO_ITEM_DEF item, tmpitem;
-
- for (item = (IIO_ITEM_DEF)arg->internal.iio_list; item; item = tmpitem) {
- tmpitem = item->next;
- jnlib_free(item);
- }
- arg->internal.iio_list = NULL;
-}
-
-/****************
- * Get options from a file.
- * Lines starting with '#' are comment lines.
- * Syntax is simply a keyword and the argument.
- * Valid keywords are all keywords from the long_opt list without
- * the leading dashes. The special keywords "help", "warranty" and "version"
- * are not valid here.
- * The special keyword "alias" may be used to store alias definitions,
- * which are later expanded like long options.
- * The option
- * ignore-invalid-option OPTIONNAMEs
- * is recognized and updates a list of option which should be ignored if they
- * are not defined.
- * Caller must free returned strings.
- * If called with FP set to NULL command line args are parse instead.
- *
- * Q: Should we allow the syntax
- * keyword = value
- * and accept for boolean options a value of 1/0, yes/no or true/false?
- * Note: Abbreviation of options is here not allowed.
- */
-int optfile_parse(FILE *fp, const char *filename, unsigned *lineno,
- ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) {
- int state, i, c;
- int idx = 0;
- char keyword[100];
- char *buffer = NULL;
- size_t buflen = 0;
- int in_alias = 0;
-
- if (!fp) /* Divert to to arg_parse() in this case. */
- return arg_parse(arg, opts);
-
- initialize(arg, filename, lineno);
-
- /* Find the next keyword. */
- state = i = 0;
- for (;;) {
- c = getc(fp);
- if (c == '\n' || c == EOF) {
- if (c != EOF) ++*lineno;
- if (state == -1)
- break;
- else if (state == 2) {
- keyword[i] = 0;
- for (i = 0; opts[i].short_opt; i++) {
- if (opts[i].long_opt && !strcmp(opts[i].long_opt, keyword)) break;
- }
- idx = i;
- arg->r_opt = opts[idx].short_opt;
- if ((opts[idx].flags & ARGPARSE_OPT_IGNORE)) {
- state = i = 0;
- continue;
- } else if (!opts[idx].short_opt) {
- if (!strcmp(keyword, "ignore-invalid-option")) {
- /* No argument - ignore this meta option. */
- state = i = 0;
- continue;
- } else if (ignore_invalid_option_p(arg, keyword)) {
- /* This invalid option is in the iio list. */
- state = i = 0;
- continue;
- }
- arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
- ? ARGPARSE_INVALID_COMMAND
- : ARGPARSE_INVALID_OPTION);
- } else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
- arg->r_type = 0; /* Does not take an arg. */
- else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
- arg->r_type = 0; /* Arg is optional. */
- else
- arg->r_opt = ARGPARSE_MISSING_ARG;
-
- break;
- } else if (state == 3) {
- /* No argument found. */
- if (in_alias)
- arg->r_opt = ARGPARSE_MISSING_ARG;
- else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
- arg->r_type = 0; /* Does not take an arg. */
- else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
- arg->r_type = 0; /* No optional argument. */
- else
- arg->r_opt = ARGPARSE_MISSING_ARG;
-
- break;
- } else if (state == 4) {
- /* Has an argument. */
- if (in_alias) {
- if (!buffer)
- arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
- else {
- char *p;
-
- buffer[i] = 0;
- p = strpbrk(buffer, " \t");
- if (p) {
- *p++ = 0;
- trim_spaces(p);
- }
- if (!p || !*p) {
- jnlib_free(buffer);
- arg->r_opt = ARGPARSE_INVALID_ALIAS;
- } else {
- store_alias(arg, buffer, p);
- }
- }
- } else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
- arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
- else {
- char *p;
-
- if (!buffer) {
- keyword[i] = 0;
- buffer = jnlib_strdup(keyword);
- if (!buffer) arg->r_opt = ARGPARSE_OUT_OF_CORE;
- } else
- buffer[i] = 0;
-
- if (buffer) {
- trim_spaces(buffer);
- p = buffer;
- if (*p == '"') {
- /* Remove quotes. */
- p++;
- if (*p && p[strlen(p) - 1] == '\"') p[strlen(p) - 1] = 0;
- }
- if (!set_opt_arg(arg, opts[idx].flags, p)) jnlib_free(buffer);
- }
- }
- break;
- } else if (c == EOF) {
- ignore_invalid_option_clear(arg);
- if (ferror(fp))
- arg->r_opt = ARGPARSE_READ_ERROR;
- else
- arg->r_opt = 0; /* EOF. */
- break;
- }
- state = 0;
- i = 0;
- } else if (state == -1)
- ; /* Skip. */
- else if (state == 0 && isascii(c) && isspace(c))
- ; /* Skip leading white space. */
- else if (state == 0 && c == '#')
- state = 1; /* Start of a comment. */
- else if (state == 1)
- ; /* Skip comments. */
- else if (state == 2 && isascii(c) && isspace(c)) {
- /* Check keyword. */
- keyword[i] = 0;
- for (i = 0; opts[i].short_opt; i++)
- if (opts[i].long_opt && !strcmp(opts[i].long_opt, keyword)) break;
- idx = i;
- arg->r_opt = opts[idx].short_opt;
- if ((opts[idx].flags & ARGPARSE_OPT_IGNORE)) {
- state = 1; /* Process like a comment. */
- } else if (!opts[idx].short_opt) {
- if (!strcmp(keyword, "alias")) {
- in_alias = 1;
- state = 3;
- } else if (!strcmp(keyword, "ignore-invalid-option")) {
- if (ignore_invalid_option_add(arg, fp)) {
- arg->r_opt = ARGPARSE_OUT_OF_CORE;
- break;
- }
- state = i = 0;
- ++*lineno;
- } else if (ignore_invalid_option_p(arg, keyword))
- state = 1; /* Process like a comment. */
- else {
- arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
- ? ARGPARSE_INVALID_COMMAND
- : ARGPARSE_INVALID_OPTION);
- state = -1; /* Skip rest of line and leave. */
- }
- } else
- state = 3;
- } else if (state == 3) {
- /* Skip leading spaces of the argument. */
- if (!isascii(c) || !isspace(c)) {
- i = 0;
- keyword[i++] = c;
- state = 4;
- }
- } else if (state == 4) {
- /* Collect the argument. */
- if (buffer) {
- if (i < buflen - 1)
- buffer[i++] = c;
- else {
- char *tmp;
- size_t tmplen = buflen + 50;
-
- tmp = (char *)jnlib_realloc(buffer, tmplen);
- if (tmp) {
- buflen = tmplen;
- buffer = tmp;
- buffer[i++] = c;
- } else {
- jnlib_free(buffer);
- arg->r_opt = ARGPARSE_OUT_OF_CORE;
- break;
- }
- }
- } else if (i < DIM(keyword) - 1)
- keyword[i++] = c;
- else {
- size_t tmplen = DIM(keyword) + 50;
- buffer = (char *)jnlib_malloc(tmplen);
- if (buffer) {
- buflen = tmplen;
- memcpy(buffer, keyword, i);
- buffer[i++] = c;
- } else {
- arg->r_opt = ARGPARSE_OUT_OF_CORE;
- break;
- }
- }
- } else if (i >= DIM(keyword) - 1) {
- arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG;
- state = -1; /* Skip rest of line and leave. */
- } else {
- keyword[i++] = c;
- state = 2;
- }
- }
-
- return arg->r_opt;
-}
-
-static int find_long_option(ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts,
- const char *keyword) {
- int i;
- size_t n;
-
- (void)arg;
-
- /* Would be better if we can do a binary search, but it is not
- possible to reorder our option table because we would mess
- up our help strings - What we can do is: Build a nice option
- lookup table when this function is first invoked */
- if (!*keyword) return -1;
- for (i = 0; opts[i].short_opt; i++)
- if (opts[i].long_opt && !strcmp(opts[i].long_opt, keyword)) return i;
-#if 0
- {
- ALIAS_DEF a;
- /* see whether it is an alias */
- for( a = args->internal.aliases; a; a = a->next ) {
- if( !strcmp( a->name, keyword) ) {
- /* todo: must parse the alias here */
- args->internal.cur_alias = a;
- return -3; /* alias available */
- }
- }
- }
-#endif
- /* not found, see whether it is an abbreviation */
- /* aliases may not be abbreviated */
- n = strlen(keyword);
- for (i = 0; opts[i].short_opt; i++) {
- if (opts[i].long_opt && !strncmp(opts[i].long_opt, keyword, n)) {
- int j;
- for (j = i + 1; opts[j].short_opt; j++) {
- if (opts[j].long_opt && !strncmp(opts[j].long_opt, keyword, n))
- return -2; /* abbreviation is ambiguous */
- }
- return i;
- }
- }
- return -1; /* Not found. */
-}
-
-int arg_parse(ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) {
- int idx;
- int argc;
- char **argv;
- char *s, *s2;
- int i;
-
- initialize(arg, NULL, NULL);
- argc = *arg->argc;
- argv = *arg->argv;
- idx = arg->internal.idx;
-
- if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0)) {
- /* Skip the first argument. */
- argc--;
- argv++;
- idx++;
- }
-
-next_one:
- if (!argc) {
- /* No more args. */
- arg->r_opt = 0;
- goto leave; /* Ready. */
- }
-
- s = *argv;
- arg->internal.last = s;
-
- if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL)) {
- arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */
- arg->r_type = 2;
- arg->r.ret_str = s;
- argc--;
- argv++;
- idx++; /* set to next one */
- } else if (arg->internal.stopped) {
- arg->r_opt = 0;
- goto leave; /* Ready. */
- } else if (*s == '-' && s[1] == '-') {
- /* Long option. */
- char *argpos;
-
- arg->internal.inarg = 0;
- if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP)) {
- /* Stop option processing. */
- arg->internal.stopped = 1;
- arg->flags |= ARGPARSE_FLAG_STOP_SEEN;
- argc--;
- argv++;
- idx++;
- goto next_one;
- }
-
- argpos = strchr(s + 2, '=');
- if (argpos) *argpos = 0;
- i = find_long_option(arg, opts, s + 2);
- if (argpos) *argpos = '=';
-
- if (i < 0 && !strcmp("help", s + 2))
- show_help(opts, arg->flags);
- else if (i < 0 && !strcmp("version", s + 2)) {
- if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) {
- show_version();
- exit(0);
- }
- } else if (i < 0 && !strcmp("warranty", s + 2)) {
- writestrings(0, strusage(16), "\n", NULL);
- exit(0);
- } else if (i < 0 && !strcmp("dump-options", s + 2)) {
- for (i = 0; opts[i].short_opt; i++) {
- if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE))
- writestrings(0, "--", opts[i].long_opt, "\n", NULL);
- }
- writestrings(0, "--dump-options\n--help\n--version\n--warranty\n", NULL);
- exit(0);
- }
-
- if (i == -2)
- arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION;
- else if (i == -1) {
- arg->r_opt = ARGPARSE_INVALID_OPTION;
- arg->r.ret_str = s + 2;
- } else
- arg->r_opt = opts[i].short_opt;
- if (i < 0)
- ;
- else if ((opts[i].flags & ARGPARSE_TYPE_MASK)) {
- if (argpos) {
- s2 = argpos + 1;
- if (!*s2) s2 = NULL;
- } else
- s2 = argv[1];
- if (!s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL)) {
- arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */
- } else if (!s2) {
- arg->r_opt = ARGPARSE_MISSING_ARG;
- } else if (!argpos && *s2 == '-' &&
- (opts[i].flags & ARGPARSE_OPT_OPTIONAL)) {
- /* The argument is optional and the next seems to be an
- option. We do not check this possible option but
- assume no argument */
- arg->r_type = ARGPARSE_TYPE_NONE;
- } else {
- set_opt_arg(arg, opts[i].flags, s2);
- if (!argpos) {
- argc--;
- argv++;
- idx++; /* Skip one. */
- }
- }
- } else {
- /* Does not take an argument. */
- if (argpos)
- arg->r_type = ARGPARSE_UNEXPECTED_ARG;
- else
- arg->r_type = 0;
- }
- argc--;
- argv++;
- idx++; /* Set to next one. */
- } else if ((*s == '-' && s[1]) || arg->internal.inarg) {
- /* Short option. */
- int dash_kludge = 0;
-
- i = 0;
- if (!arg->internal.inarg) {
- arg->internal.inarg++;
- if ((arg->flags & ARGPARSE_FLAG_ONEDASH)) {
- for (i = 0; opts[i].short_opt; i++)
- if (opts[i].long_opt && !strcmp(opts[i].long_opt, s + 1)) {
- dash_kludge = 1;
- break;
- }
- }
- }
- s += arg->internal.inarg;
-
- if (!dash_kludge) {
- for (i = 0; opts[i].short_opt; i++)
- if (opts[i].short_opt == *s) break;
- }
-
- if (!opts[i].short_opt && (*s == 'h' || *s == '?'))
- show_help(opts, arg->flags);
-
- arg->r_opt = opts[i].short_opt;
- if (!opts[i].short_opt) {
- arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)
- ? ARGPARSE_INVALID_COMMAND
- : ARGPARSE_INVALID_OPTION;
- arg->internal.inarg++; /* Point to the next arg. */
- arg->r.ret_str = s;
- } else if ((opts[i].flags & ARGPARSE_TYPE_MASK)) {
- if (s[1] && !dash_kludge) {
- s2 = s + 1;
- set_opt_arg(arg, opts[i].flags, s2);
- } else {
- s2 = argv[1];
- if (!s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL)) {
- arg->r_type = ARGPARSE_TYPE_NONE;
- } else if (!s2) {
- arg->r_opt = ARGPARSE_MISSING_ARG;
- } else if (*s2 == '-' && s2[1] &&
- (opts[i].flags & ARGPARSE_OPT_OPTIONAL)) {
- /* The argument is optional and the next seems to
- be an option. We do not check this possible
- option but assume no argument. */
- arg->r_type = ARGPARSE_TYPE_NONE;
- } else {
- set_opt_arg(arg, opts[i].flags, s2);
- argc--;
- argv++;
- idx++; /* Skip one. */
- }
- }
- s = "x"; /* This is so that !s[1] yields false. */
- } else {
- /* Does not take an argument. */
- arg->r_type = ARGPARSE_TYPE_NONE;
- arg->internal.inarg++; /* Point to the next arg. */
- }
- if (!s[1] || dash_kludge) {
- /* No more concatenated short options. */
- arg->internal.inarg = 0;
- argc--;
- argv++;
- idx++;
- }
- } else if (arg->flags & ARGPARSE_FLAG_MIXED) {
- arg->r_opt = ARGPARSE_IS_ARG;
- arg->r_type = 2;
- arg->r.ret_str = s;
- argc--;
- argv++;
- idx++; /* Set to next one. */
- } else {
- arg->internal.stopped = 1; /* Stop option processing. */
- goto next_one;
- }
-
-leave:
- *arg->argc = argc;
- *arg->argv = argv;
- arg->internal.idx = idx;
- return arg->r_opt;
-}
-
-/* Returns: -1 on error, 0 for an integer type and 1 for a non integer
- type argument. */
-static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s) {
- int base = (flags & ARGPARSE_OPT_PREFIX) ? 0 : 10;
- long l;
-
- switch ((arg->r_type = (flags & ARGPARSE_TYPE_MASK))) {
- case ARGPARSE_TYPE_LONG:
- case ARGPARSE_TYPE_INT:
- errno = 0;
- l = strtol(s, NULL, base);
- if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) {
- arg->r_opt = ARGPARSE_INVALID_ARG;
- return -1;
- }
- if (arg->r_type == ARGPARSE_TYPE_LONG)
- arg->r.ret_long = l;
- else if ((l < 0 && l < INT_MIN) || l > INT_MAX) {
- arg->r_opt = ARGPARSE_INVALID_ARG;
- return -1;
- } else
- arg->r.ret_int = (int)l;
- return 0;
-
- case ARGPARSE_TYPE_ULONG:
- while (isascii(*s) && isspace(*s)) s++;
- if (*s == '-') {
- arg->r.ret_ulong = 0;
- arg->r_opt = ARGPARSE_INVALID_ARG;
- return -1;
- }
- errno = 0;
- arg->r.ret_ulong = strtoul(s, NULL, base);
- if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE) {
- arg->r_opt = ARGPARSE_INVALID_ARG;
- return -1;
- }
- return 0;
-
- case ARGPARSE_TYPE_STRING:
- default:
- arg->r.ret_str = s;
- return 1;
- }
-}
-
-static size_t long_opt_strlen(ARGPARSE_OPTS *o) {
- size_t n = strlen(o->long_opt);
-
- if (o->description && *o->description == '|') {
- const char *s;
-#ifdef JNLIB_NEED_UTF8CONV
- int is_utf8 = is_native_utf8();
-#endif
-
- s = o->description + 1;
- if (*s != '=') n++;
- /* For a (mostly) correct length calculation we exclude
- continuation bytes (10xxxxxx) if we are on a native utf8
- terminal. */
- for (; *s && *s != '|'; s++)
-#ifdef JNLIB_NEED_UTF8CONV
- if (is_utf8 && (*s & 0xc0) != 0x80)
-#endif
- n++;
- }
- return n;
-}
-
-/****************
- * Print formatted help. The description string has some special
- * meanings:
- * - A description string which is "@" suppresses help output for
- * this option
- * - a description,ine which starts with a '@' and is followed by
- * any other characters is printed as is; this may be used for examples
- * ans such.
- * - A description which starts with a '|' outputs the string between this
- * bar and the next one as arguments of the long option.
- */
-static void show_help(ARGPARSE_OPTS *opts, unsigned int flags) {
- const char *s;
- char tmp[2];
-
- show_version();
- writestrings(0, "\n", NULL);
- s = strusage(42);
- if (s && *s == '1') {
- s = strusage(40);
- writestrings(1, s, NULL);
- if (*s && s[strlen(s)] != '\n') writestrings(1, "\n", NULL);
- }
- s = strusage(41);
- writestrings(0, s, "\n", NULL);
- if (opts[0].description) {
- /* Auto format the option description. */
- int i, j, indent;
-
- /* Get max. length of long options. */
- for (i = indent = 0; opts[i].short_opt; i++) {
- if (opts[i].long_opt)
- if (!opts[i].description || *opts[i].description != '@')
- if ((j = long_opt_strlen(opts + i)) > indent && j < 35) indent = j;
- }
-
- /* Example: " -v, --verbose Viele Sachen ausgeben" */
- indent += 10;
- if (*opts[0].description != '@') writestrings(0, "Options:", "\n", NULL);
- for (i = 0; opts[i].short_opt; i++) {
- s = map_static_macro_string(_(opts[i].description));
- if (s && *s == '@' && !s[1]) /* Hide this line. */
- continue;
- if (s && *s == '@') /* Unindented comment only line. */
- {
- for (s++; *s; s++) {
- if (*s == '\n') {
- if (s[1]) writestrings(0, "\n", NULL);
- } else {
- tmp[0] = *s;
- tmp[1] = 0;
- writestrings(0, tmp, NULL);
- }
- }
- writestrings(0, "\n", NULL);
- continue;
- }
-
- j = 3;
- if (opts[i].short_opt < 256) {
- tmp[0] = opts[i].short_opt;
- tmp[1] = 0;
- writestrings(0, " -", tmp, NULL);
- if (!opts[i].long_opt) {
- if (s && *s == '|') {
- writestrings(0, " ", NULL);
- j++;
- for (s++; *s && *s != '|'; s++, j++) {
- tmp[0] = *s;
- tmp[1] = 0;
- writestrings(0, tmp, NULL);
- }
- if (*s) s++;
- }
- }
- } else
- writestrings(0, " ", NULL);
- if (opts[i].long_opt) {
- tmp[0] = opts[i].short_opt < 256 ? ',' : ' ';
- tmp[1] = 0;
- j += writestrings(0, tmp, " --", opts[i].long_opt, NULL);
- if (s && *s == '|') {
- if (*++s != '=') {
- writestrings(0, " ", NULL);
- j++;
- }
- for (; *s && *s != '|'; s++, j++) {
- tmp[0] = *s;
- tmp[1] = 0;
- writestrings(0, tmp, NULL);
- }
- if (*s) s++;
- }
- writestrings(0, " ", NULL);
- j += 3;
- }
- for (; j < indent; j++) writestrings(0, " ", NULL);
- if (s) {
- if (*s && j > indent) {
- writestrings(0, "\n", NULL);
- for (j = 0; j < indent; j++) writestrings(0, " ", NULL);
- }
- for (; *s; s++) {
- if (*s == '\n') {
- if (s[1]) {
- writestrings(0, "\n", NULL);
- for (j = 0; j < indent; j++) writestrings(0, " ", NULL);
- }
- } else {
- tmp[0] = *s;
- tmp[1] = 0;
- writestrings(0, tmp, NULL);
- }
- }
- }
- writestrings(0, "\n", NULL);
- }
- if ((flags & ARGPARSE_FLAG_ONEDASH))
- writestrings(0,
- "\n(A single dash may be used "
- "instead of the double ones)\n",
- NULL);
- }
- if ((s = strusage(19))) {
- writestrings(0, "\n", NULL);
- writestrings(0, s, NULL);
- }
- flushstrings(0);
- exit(0);
-}
-
-static void show_version(void) {
- const char *s;
- int i;
-
- /* Version line. */
- writestrings(0, strusage(11), NULL);
- if ((s = strusage(12))) writestrings(0, " (", s, ")", NULL);
- writestrings(0, " ", strusage(13), "\n", NULL);
- /* Additional version lines. */
- for (i = 20; i < 30; i++)
- if ((s = strusage(i))) writestrings(0, s, "\n", NULL);
- /* Copyright string. */
- if ((s = strusage(14))) writestrings(0, s, "\n", NULL);
- /* Licence string. */
- if ((s = strusage(10))) writestrings(0, s, "\n", NULL);
- /* Copying conditions. */
- if ((s = strusage(15))) writestrings(0, s, NULL);
- /* Thanks. */
- if ((s = strusage(18))) writestrings(0, s, NULL);
- /* Additional program info. */
- for (i = 30; i < 40; i++)
- if ((s = strusage(i))) writestrings(0, s, NULL);
- flushstrings(0);
-}
-
-void usage(int level) {
- const char *p;
-
- if (!level) {
- writestrings(1, strusage(11), " ", strusage(13), "; ", strusage(14), "\n",
- NULL);
- flushstrings(1);
- } else if (level == 1) {
- p = strusage(40);
- writestrings(1, p, NULL);
- if (*p && p[strlen(p)] != '\n') writestrings(1, "\n", NULL);
- exit(2);
- } else if (level == 2) {
- p = strusage(42);
- if (p && *p == '1') {
- p = strusage(40);
- writestrings(1, p, NULL);
- if (*p && p[strlen(p)] != '\n') writestrings(1, "\n", NULL);
- }
- writestrings(0, strusage(41), "\n", NULL);
- exit(0);
- }
-}
-
-/* Level
- * 0: Print copyright string to stderr
- * 1: Print a short usage hint to stderr and terminate
- * 2: Print a long usage hint to stdout and terminate
- * 10: Return license info string
- * 11: Return the name of the program
- * 12: Return optional name of package which includes this program.
- * 13: version string
- * 14: copyright string
- * 15: Short copying conditions (with LFs)
- * 16: Long copying conditions (with LFs)
- * 17: Optional printable OS name
- * 18: Optional thanks list (with LFs)
- * 19: Bug report info
- *20..29: Additional lib version strings.
- *30..39: Additional program info (with LFs)
- * 40: short usage note (with LF)
- * 41: long usage note (with LF)
- * 42: Flag string:
- * First char is '1':
- * The short usage notes needs to be printed
- * before the long usage note.
- */
-const char *strusage(int level) {
- const char *p = strusage_handler ? strusage_handler(level) : NULL;
-
- if (p) return map_static_macro_string(p);
-
- switch (level) {
- case 10:
-#if ARGPARSE_GPL_VERSION == 3
- p =
- ("License GPLv3+: GNU GPL version 3 or later "
- "<https://www.gnu.org/licenses/gpl.html>");
-#else
- p =
- ("License GPLv2+: GNU GPL version 2 or later "
- "<https://www.gnu.org/licenses/>");
-#endif
- break;
- case 11:
- p = "foo";
- break;
- case 13:
- p = "0.0";
- break;
- case 14:
- p = ARGPARSE_CRIGHT_STR;
- break;
- case 15:
- p = "This is free software: you are free to change and redistribute it.\n"
- "There is NO WARRANTY, to the extent permitted by law.\n";
- break;
- case 16:
- p =
-"This is free software; you can redistribute it and/or modify\n"
-"it under the terms of the GNU General Public License as published by\n"
-"the Free Software Foundation; either version "
-ARGPARSE_STR2(ARGPARSE_GPL_VERSION)
-" of the License, or\n"
-"(at your option) any later version.\n\n"
-"It is distributed in the hope that it will be useful,\n"
-"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
-"GNU General Public License for more details.\n\n"
-"You should have received a copy of the GNU General Public License\n"
-"along with this software. If not, see <https://www.gnu.org/licenses/>.\n";
- break;
- case 40: /* short and long usage */
- case 41:
- p = "";
- break;
- }
-
- return p;
-}
-
-/* Set the usage handler. This function is basically a constructor. */
-void set_strusage(const char *(*f)(int)) { strusage_handler = f; }
-
-#ifdef TEST
-static struct {
- int verbose;
- int debug;
- char *outfile;
- char *crf;
- int myopt;
- int echo;
- int a_long_one;
-} opt;
-
-int main(int argc, char **argv) {
- ARGPARSE_OPTS opts[] = {
- ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"),
- ARGPARSE_s_n('e', "echo",
- ("Zeile ausgeben, damit wir sehen, "
- "was wir eingegeben haben")),
- ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"),
- ARGPARSE_s_s('o', "output", 0),
- ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n"),
- /* Note that on a non-utf8 terminal the ß might garble the output. */
- ARGPARSE_s_n('s', "street",
- "|Straße|set the name of the street to Straße"),
- ARGPARSE_o_i('m', "my-option", 0), ARGPARSE_s_n(500, "a-long-option", 0),
- ARGPARSE_end()};
- ARGPARSE_ARGS pargs = {
- &argc, &argv,
- (ARGPARSE_FLAG_ALL | ARGPARSE_FLAG_MIXED | ARGPARSE_FLAG_ONEDASH)};
- int i;
-
- while (arg_parse(&pargs, opts)) {
- switch (pargs.r_opt) {
- case ARGPARSE_IS_ARG:
- printf("arg='%s'\n", pargs.r.ret_str);
- break;
- case 'v':
- opt.verbose++;
- break;
- case 'e':
- opt.echo++;
- break;
- case 'd':
- opt.debug++;
- break;
- case 'o':
- opt.outfile = pargs.r.ret_str;
- break;
- case 'c':
- opt.crf = pargs.r_type ? pargs.r.ret_str : "a.crf";
- break;
- case 'm':
- opt.myopt = pargs.r_type ? pargs.r.ret_int : 1;
- break;
- case 500:
- opt.a_long_one++;
- break;
- default:
- pargs.err = ARGPARSE_PRINT_WARNING;
- break;
- }
- }
- for (i = 0; i < argc; i++) printf("%3d -> (%s)\n", i, argv[i]);
- puts("Options:");
- if (opt.verbose) printf(" verbose=%d\n", opt.verbose);
- if (opt.debug) printf(" debug=%d\n", opt.debug);
- if (opt.outfile) printf(" outfile='%s'\n", opt.outfile);
- if (opt.crf) printf(" crffile='%s'\n", opt.crf);
- if (opt.myopt) printf(" myopt=%d\n", opt.myopt);
- if (opt.a_long_one) printf(" a-long-one=%d\n", opt.a_long_one);
- if (opt.echo) printf(" echo=%d\n", opt.echo);
-
- return 0;
-}
-#endif /*TEST*/
-
-/**** bottom of file ****/
diff --git a/src/pinentry/argparse.h b/src/pinentry/argparse.h
deleted file mode 100644
index 5b652eba..00000000
--- a/src/pinentry/argparse.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/* argparse.h - Argument parser for option handling.
- * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc.
- *
- * This file is part of JNLIB, which is a subsystem of GnuPG.
- *
- * JNLIB is free software; you can redistribute it and/or modify it
- * under the terms of either
- *
- * - the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at
- * your option) any later version.
- *
- * or
- *
- * - the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * or both in parallel, as here.
- *
- * JNLIB is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copies of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, see <https://www.gnu.org/licenses/>.
- * SPDX-License-Identifier: (GPL-2.0+ OR LGPL-3.0+)
- */
-
-#ifndef LIBJNLIB_ARGPARSE_H
-#define LIBJNLIB_ARGPARSE_H
-
-#include <stdio.h>
-
-typedef struct
-{
- int *argc; /* Pointer to ARGC (value subject to change). */
- char ***argv; /* Pointer to ARGV (value subject to change). */
- unsigned int flags; /* Global flags. May be set prior to calling the
- parser. The parser may change the value. */
- int err; /* Print error description for last option.
- Either 0, ARGPARSE_PRINT_WARNING or
- ARGPARSE_PRINT_ERROR. */
-
- int r_opt; /* Returns option code. */
- int r_type; /* Returns type of option value. */
- union {
- int ret_int;
- long ret_long;
- unsigned long ret_ulong;
- char *ret_str;
- } r; /* Return values */
-
- struct {
- int idx;
- int inarg;
- int stopped;
- const char *last;
- void *aliases;
- const void *cur_alias;
- void *iio_list;
- } internal; /* Private - do not change. */
-} ARGPARSE_ARGS;
-
-typedef struct
-{
- int short_opt;
- const char *long_opt;
- unsigned int flags;
- const char *description; /* Optional option description. */
-} ARGPARSE_OPTS;
-
-
-/* Global flags (ARGPARSE_ARGS). */
-#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */
-#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return
- remaining args with R_OPT set to -1. */
-#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */
-#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */
-#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */
-#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */
-#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */
-
-#define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */
-
-/* Flags for each option (ARGPARSE_OPTS). The type code may be
- ORed with the OPT flags. */
-#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */
-#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */
-#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */
-#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */
-#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */
-#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */
-#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */
-#define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */
-#define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */
-
-#define ARGPARSE_TYPE_MASK 7 /* Mask for the type values (internal). */
-
-/* A set of macros to make option definitions easier to read. */
-#define ARGPARSE_x(s,l,t,f,d) \
- { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) }
-
-#define ARGPARSE_s(s,l,t,d) \
- { (s), (l), ARGPARSE_TYPE_ ## t, (d) }
-#define ARGPARSE_s_n(s,l,d) \
- { (s), (l), ARGPARSE_TYPE_NONE, (d) }
-#define ARGPARSE_s_i(s,l,d) \
- { (s), (l), ARGPARSE_TYPE_INT, (d) }
-#define ARGPARSE_s_s(s,l,d) \
- { (s), (l), ARGPARSE_TYPE_STRING, (d) }
-#define ARGPARSE_s_l(s,l,d) \
- { (s), (l), ARGPARSE_TYPE_LONG, (d) }
-#define ARGPARSE_s_u(s,l,d) \
- { (s), (l), ARGPARSE_TYPE_ULONG, (d) }
-
-#define ARGPARSE_o(s,l,t,d) \
- { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) }
-#define ARGPARSE_o_n(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) }
-#define ARGPARSE_o_i(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) }
-#define ARGPARSE_o_s(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) }
-#define ARGPARSE_o_l(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) }
-#define ARGPARSE_o_u(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) }
-
-#define ARGPARSE_p(s,l,t,d) \
- { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_p_n(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_p_i(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_p_s(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_p_l(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_p_u(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) }
-
-#define ARGPARSE_op(s,l,t,d) \
- { (s), (l), (ARGPARSE_TYPE_ ## t \
- | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_op_n(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_NONE \
- | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_op_i(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_INT \
- | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_op_s(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_STRING \
- | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_op_l(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_LONG \
- | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
-#define ARGPARSE_op_u(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_ULONG \
- | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
-
-#define ARGPARSE_c(s,l,d) \
- { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) }
-
-#define ARGPARSE_ignore(s,l) \
- { (s), (l), (ARGPARSE_OPT_IGNORE), "@" }
-
-#define ARGPARSE_group(s,d) \
- { (s), NULL, 0, (d) }
-
-#define ARGPARSE_end() { 0, NULL, 0, NULL }
-
-
-/* Other constants. */
-#define ARGPARSE_PRINT_WARNING 1
-#define ARGPARSE_PRINT_ERROR 2
-
-
-/* Error values. */
-#define ARGPARSE_IS_ARG (-1)
-#define ARGPARSE_INVALID_OPTION (-2)
-#define ARGPARSE_MISSING_ARG (-3)
-#define ARGPARSE_KEYWORD_TOO_LONG (-4)
-#define ARGPARSE_READ_ERROR (-5)
-#define ARGPARSE_UNEXPECTED_ARG (-6)
-#define ARGPARSE_INVALID_COMMAND (-7)
-#define ARGPARSE_AMBIGUOUS_OPTION (-8)
-#define ARGPARSE_AMBIGUOUS_COMMAND (-9)
-#define ARGPARSE_INVALID_ALIAS (-10)
-#define ARGPARSE_OUT_OF_CORE (-11)
-#define ARGPARSE_INVALID_ARG (-12)
-
-
-int arg_parse (ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
-int optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
- ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
-void usage (int level);
-const char *strusage (int level);
-void set_strusage (const char *(*f)( int ));
-void argparse_register_outfnc (int (*fnc)(int, const char *));
-
-#endif /*LIBJNLIB_ARGPARSE_H*/
diff --git a/src/pinentry/capslock/capslock.cpp b/src/pinentry/capslock/capslock.cpp
index 3ff0b779..a730c220 100644
--- a/src/pinentry/capslock/capslock.cpp
+++ b/src/pinentry/capslock/capslock.cpp
@@ -18,10 +18,6 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <QDebug>
#include <QGuiApplication>
diff --git a/src/pinentry/password_cache.cpp b/src/pinentry/password_cache.cpp
deleted file mode 100644
index b52602d7..00000000
--- a/src/pinentry/password_cache.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/* password-cache.c - Password cache support.
- Copyright (C) 2015 g10 Code GmbH
-
- This file is part of PINENTRY.
-
- PINENTRY is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- PINENTRY is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>.
- SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_LIBSECRET
-#include <libsecret/secret.h>
-#endif
-
-#include "password_cache.h"
-#include "secmem.h"
-
-#ifdef HAVE_LIBSECRET
-static const SecretSchema *gpg_schema(void) {
- static const SecretSchema the_schema = {
- "org.gnupg.Passphrase",
- SECRET_SCHEMA_NONE,
- {
- {"stored-by", SECRET_SCHEMA_ATTRIBUTE_STRING},
- {"keygrip", SECRET_SCHEMA_ATTRIBUTE_STRING},
- {"NULL", 0},
- }};
- return &the_schema;
-}
-
-static char *keygrip_to_label(const char *keygrip) {
- char const prefix[] = "GnuPG: ";
- char *label;
-
- label = malloc(sizeof(prefix) + strlen(keygrip));
- if (label) {
- memcpy(label, prefix, sizeof(prefix) - 1);
- strcpy(&label[sizeof(prefix) - 1], keygrip);
- }
- return label;
-}
-#endif
-
-void password_cache_save(const char *keygrip, const char *password) {
-#ifdef HAVE_LIBSECRET
- char *label;
- GError *error = NULL;
-
- if (!*keygrip) return;
-
- label = keygrip_to_label(keygrip);
- if (!label) return;
-
- if (!secret_password_store_sync(gpg_schema(), SECRET_COLLECTION_DEFAULT,
- label, password, NULL, &error, "stored-by",
- "GnuPG Pinentry", "keygrip", keygrip, NULL)) {
- fprintf(stderr,
- "Failed to cache password for key %s with secret service: %s\n",
- keygrip, error->message);
-
- g_error_free(error);
- }
-
- free(label);
-#else
- (void)keygrip;
- (void)password;
- return;
-#endif
-}
-
-char *password_cache_lookup(const char *keygrip, int *fatal_error) {
-#ifdef HAVE_LIBSECRET
- GError *error = NULL;
- char *password;
- char *password2;
-
- if (!*keygrip) return NULL;
-
- password = secret_password_lookup_nonpageable_sync(gpg_schema(), NULL, &error,
- "keygrip", keygrip, NULL);
-
- if (error != NULL) {
- if (fatal_error) *fatal_error = 1;
-
- fprintf(stderr,
- "Failed to lookup password for key %s with secret service: %s\n",
- keygrip, error->message);
- g_error_free(error);
- return NULL;
- }
- if (!password)
- /* The password for this key is not cached. Just return NULL. */
- return NULL;
-
- /* The password needs to be returned in secmem allocated memory. */
- password2 = secmem_malloc(strlen(password) + 1);
- if (password2)
- strcpy(password2, password);
- else
- fprintf(stderr, "secmem_malloc failed: can't copy password!\n");
-
- secret_password_free(password);
-
- return password2;
-#else
- (void)keygrip;
- (void)fatal_error;
- return NULL;
-#endif
-}
-
-/* Try and remove the cached password for key grip. Returns -1 on
- error, 0 if the key is not found and 1 if the password was
- removed. */
-int password_cache_clear(const char *keygrip) {
-#ifdef HAVE_LIBSECRET
- GError *error = NULL;
- int removed = secret_password_clear_sync(gpg_schema(), NULL, &error,
- "keygrip", keygrip, NULL);
- if (error != NULL) {
- fprintf(stderr,
- "Failed to clear password for key %s with secret service: %s\n",
- keygrip, error->message);
- g_debug("%s", error->message);
- g_error_free(error);
- return -1;
- }
- if (removed) return 1;
- return 0;
-#else
- (void)keygrip;
- return -1;
-#endif
-}
diff --git a/src/pinentry/password_cache.h b/src/pinentry/password_cache.h
deleted file mode 100644
index cdba356d..00000000
--- a/src/pinentry/password_cache.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* password_cache.h - Password cache support interfaces.
- Copyright (C) 2015 g10 Code GmbH
-
- This file is part of PINENTRY.
-
- PINENTRY is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- PINENTRY is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>.
- SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef PASSWORD_CACHE_H
-#define PASSWORD_CACHE_H
-
-void password_cache_save(const char *key_grip, const char *password);
-
-char *password_cache_lookup(const char *key_grip, int *fatal_error);
-
-int password_cache_clear(const char *keygrip);
-
-#endif
diff --git a/src/pinentry/pinentry.cpp b/src/pinentry/pinentry.cpp
index 918944b9..79b2450b 100644
--- a/src/pinentry/pinentry.cpp
+++ b/src/pinentry/pinentry.cpp
@@ -44,10 +44,8 @@
#include <assuan.h>
-#include "argparse.h"
-#include "password_cache.h"
+#include "core/utils/MemoryUtils.h"
#include "pinentry.h"
-#include "secmem_util.h"
#ifdef WINDOWS
#define getpid() GetCurrentProcessId()
@@ -145,7 +143,7 @@ static void pinentry_reset(int use_defaults) {
free(pinentry.ok);
free(pinentry.notok);
free(pinentry.cancel);
- secmem_free(pinentry.pin);
+ GpgFrontend::SecureFree(pinentry.pin);
free(pinentry.repeat_passphrase);
free(pinentry.repeat_error_string);
free(pinentry.quality_bar);
@@ -415,12 +413,13 @@ int pinentry_inq_quality(pinentry_t pin, const char *passphrase,
length = 300; /* Limit so that it definitely fits into an Assuan
line. */
- command = (char *)secmem_malloc(strlen(prefix) + 3 * length + 1);
+ command =
+ GpgFrontend::SecureMallocAsType<char>(strlen(prefix) + 3 * length + 1);
if (!command) return 0;
strcpy(command, prefix);
copy_and_escape(command + strlen(command), passphrase, length);
rc = assuan_write_line(ctx, command);
- secmem_free(command);
+ GpgFrontend::SecureFree(command);
if (rc) {
fprintf(stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc);
return 0;
@@ -473,12 +472,13 @@ char *pinentry_inq_checkpin(pinentry_t pin, const char *passphrase,
length = 300; /* Limit so that it definitely fits into an Assuan
line. */
- command = (char *)secmem_malloc(strlen(prefix) + 3 * length + 1);
+ command =
+ GpgFrontend::SecureMallocAsType<char>(strlen(prefix) + 3 * length + 1);
if (!command) return 0;
strcpy(command, prefix);
copy_and_escape(command + strlen(command), passphrase, length);
rc = assuan_write_line(ctx, command);
- secmem_free(command);
+ GpgFrontend::SecureFree(command);
if (rc) {
fprintf(stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc);
return 0;
@@ -568,12 +568,12 @@ char *pinentry_setbufferlen(pinentry_t pin, int len) {
if (len <= pin->pin_len) return pin->pin;
- newp = (char *)secmem_realloc(pin->pin, len);
+ newp = GpgFrontend::SecureReallocAsType<char>(pin->pin, len);
if (newp) {
pin->pin = newp;
pin->pin_len = len;
} else {
- secmem_free(pin->pin);
+ GpgFrontend::SecureFree(pin->pin);
pin->pin = 0;
pin->pin_len = 0;
}
@@ -588,7 +588,7 @@ static void pinentry_setbuffer_clear(pinentry_t pin) {
assert(pin->pin_len > 0);
- secmem_free(pin->pin);
+ GpgFrontend::SecureFree(pin->pin);
pin->pin = NULL;
pin->pin_len = 0;
}
@@ -609,14 +609,15 @@ void pinentry_setbuffer_use(pinentry_t pin, char *passphrase, int len) {
if (passphrase && len == 0) len = strlen(passphrase) + 1;
- if (pin->pin) secmem_free(pin->pin);
+ if (pin->pin) GpgFrontend::SecureFree(pin->pin);
pin->pin = passphrase;
pin->pin_len = len;
}
static struct assuan_malloc_hooks assuan_malloc_hooks = {
- secmem_malloc, secmem_realloc, secmem_free};
+ GpgFrontend::SecureMalloc, GpgFrontend::SecureRealloc,
+ GpgFrontend::SecureFree};
/* Initialize the secure memory subsystem, drop privileges and return.
Must be called early. */
@@ -627,16 +628,6 @@ void pinentry_init(const char *pgmname) {
gpgrt_check_version(NULL);
- /* Initialize secure memory. 1 is too small, so the default size
- will be used. */
- secmem_init(1);
- secmem_set_flags(SECMEM_WARN);
- drop_privs();
-
- if (atexit(secmem_term)) {
- /* FIXME: Could not register at-exit function, bail out. */
- }
-
assuan_set_malloc_hooks(&assuan_malloc_hooks);
}
@@ -772,131 +763,6 @@ char *parse_color(char *arg, pinentry_color_t *color_p, int *bright_p) {
return new_arg;
}
-/* Parse the command line options. May exit the program if only help
- or version output is requested. */
-void pinentry_parse_opts(int argc, char *argv[]) {
- static ARGPARSE_OPTS opts[] = {
- ARGPARSE_s_n('d', "debug", "Turn on debugging output"),
- ARGPARSE_s_s('D', "display", "|DISPLAY|Set the X display"),
- ARGPARSE_s_s('T', "ttyname", "|FILE|Set the tty terminal node name"),
- ARGPARSE_s_s('N', "ttytype", "|NAME|Set the tty terminal type"),
- ARGPARSE_s_s('C', "lc-ctype", "|STRING|Set the tty LC_CTYPE value"),
- ARGPARSE_s_s('M', "lc-messages", "|STRING|Set the tty LC_MESSAGES value"),
- ARGPARSE_s_i('o', "timeout",
- "|SECS|Timeout waiting for input after this many seconds"),
- ARGPARSE_s_n('g', "no-global-grab",
- "Grab keyboard only while window is focused"),
- ARGPARSE_s_u('W', "parent-wid", "Parent window ID (for positioning)"),
- ARGPARSE_s_s('c', "colors", "|STRING|Set custom colors for ncurses"),
- ARGPARSE_s_s('a', "ttyalert",
- "|STRING|Set the alert mode (none, beep or flash)"),
- ARGPARSE_end()};
- ARGPARSE_ARGS pargs = {&argc, &argv, 0};
-
- set_strusage(my_strusage);
-
- pinentry_reset(1);
-
- while (arg_parse(&pargs, opts)) {
- switch (pargs.r_opt) {
- case 'd':
- pinentry.debug = 1;
- break;
- case 'g':
- pinentry.grab = 0;
- break;
-
- case 'D':
- /* Note, this is currently not used because the GUI engine
- has already been initialized when parsing these options. */
- pinentry.display = strdup(pargs.r.ret_str);
- if (!pinentry.display) {
-#ifndef WINDOWS
- fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno));
-#endif
- exit(EXIT_FAILURE);
- }
- break;
- case 'T':
- pinentry.ttyname = strdup(pargs.r.ret_str);
- if (!pinentry.ttyname) {
-#ifndef WINDOWS
- fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno));
-#endif
- exit(EXIT_FAILURE);
- }
- break;
- case 'N':
- pinentry.ttytype_l = strdup(pargs.r.ret_str);
- if (!pinentry.ttytype_l) {
-#ifndef WINDOWS
- fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno));
-#endif
- exit(EXIT_FAILURE);
- }
- break;
- case 'C':
- pinentry.lc_ctype = strdup(pargs.r.ret_str);
- if (!pinentry.lc_ctype) {
-#ifndef WINDOWS
- fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno));
-#endif
- exit(EXIT_FAILURE);
- }
- break;
- case 'M':
- pinentry.lc_messages = strdup(pargs.r.ret_str);
- if (!pinentry.lc_messages) {
-#ifndef WINDOWS
- fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno));
-#endif
- exit(EXIT_FAILURE);
- }
- break;
- case 'W':
- pinentry.parent_wid = pargs.r.ret_ulong;
- break;
-
- case 'c': {
- char *tmpstr = pargs.r.ret_str;
-
- tmpstr =
- parse_color(tmpstr, &pinentry.color_fg, &pinentry.color_fg_bright);
- tmpstr = parse_color(tmpstr, &pinentry.color_bg, NULL);
- tmpstr =
- parse_color(tmpstr, &pinentry.color_so, &pinentry.color_so_bright);
- tmpstr =
- parse_color(tmpstr, &pinentry.color_ok, &pinentry.color_ok_bright);
- tmpstr = parse_color(tmpstr, &pinentry.color_qualitybar,
- &pinentry.color_qualitybar_bright);
- } break;
-
- case 'o':
- pinentry.timeout = pargs.r.ret_int;
- break;
-
- case 'a':
- pinentry.ttyalert = strdup(pargs.r.ret_str);
- if (!pinentry.ttyalert) {
-#ifndef WINDOWS
- fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno));
-#endif
- exit(EXIT_FAILURE);
- }
- break;
-
- default:
- pargs.err = ARGPARSE_PRINT_WARNING;
- break;
- }
- }
-
- if (!pinentry.display && remember_display) {
- pinentry.display = remember_display;
- remember_display = NULL;
- }
-}
-
/* Set the optional flag used with getinfo. */
void pinentry_set_flavor_flag(const char *string) { flavor_flag = string; }
@@ -1073,425 +939,6 @@ static void write_status_error(assuan_context_t ctx, pinentry_t pe) {
assuan_write_status(ctx, "ERROR", buf);
}
-static gpg_error_t cmd_setdesc(assuan_context_t ctx, char *line) {
- char *newd;
-
- (void)ctx;
-
- newd = (char *)malloc(strlen(line) + 1);
- if (!newd) return gpg_error_from_syserror();
-
- strcpy_escaped(newd, line);
- if (pinentry.description) free(pinentry.description);
- pinentry.description = newd;
- return 0;
-}
-
-static gpg_error_t cmd_setprompt(assuan_context_t ctx, char *line) {
- char *newp;
-
- (void)ctx;
-
- newp = (char *)malloc(strlen(line) + 1);
- if (!newp) return gpg_error_from_syserror();
-
- strcpy_escaped(newp, line);
- if (pinentry.prompt) free(pinentry.prompt);
- pinentry.prompt = newp;
- return 0;
-}
-
-/* The data provided at LINE may be used by pinentry implementations
- to identify a key for caching strategies of its own. The empty
- string and --clear mean that the key does not have a stable
- identifier. */
-static gpg_error_t cmd_setkeyinfo(assuan_context_t ctx, char *line) {
- (void)ctx;
-
- if (pinentry.keyinfo) free(pinentry.keyinfo);
-
- if (*line && strcmp(line, "--clear") != 0)
- pinentry.keyinfo = strdup(line);
- else
- pinentry.keyinfo = NULL;
-
- return 0;
-}
-
-static gpg_error_t cmd_setrepeat(assuan_context_t ctx, char *line) {
- char *p;
-
- (void)ctx;
-
- p = (char *)malloc(strlen(line) + 1);
- if (!p) return gpg_error_from_syserror();
-
- strcpy_escaped(p, line);
- free(pinentry.repeat_passphrase);
- pinentry.repeat_passphrase = p;
- return 0;
-}
-
-static gpg_error_t cmd_setrepeatok(assuan_context_t ctx, char *line) {
- char *p;
-
- (void)ctx;
-
- p = (char *)malloc(strlen(line) + 1);
- if (!p) return gpg_error_from_syserror();
-
- strcpy_escaped(p, line);
- free(pinentry.repeat_ok_string);
- pinentry.repeat_ok_string = p;
- return 0;
-}
-
-static gpg_error_t cmd_setrepeaterror(assuan_context_t ctx, char *line) {
- char *p;
-
- (void)ctx;
-
- p = (char *)malloc(strlen(line) + 1);
- if (!p) return gpg_error_from_syserror();
-
- strcpy_escaped(p, line);
- free(pinentry.repeat_error_string);
- pinentry.repeat_error_string = p;
- return 0;
-}
-
-static gpg_error_t cmd_seterror(assuan_context_t ctx, char *line) {
- char *newe;
-
- (void)ctx;
-
- newe = (char *)malloc(strlen(line) + 1);
- if (!newe) return gpg_error_from_syserror();
-
- strcpy_escaped(newe, line);
- if (pinentry.error) free(pinentry.error);
- pinentry.error = newe;
- return 0;
-}
-
-static gpg_error_t cmd_setok(assuan_context_t ctx, char *line) {
- char *newo;
-
- (void)ctx;
-
- newo = (char *)malloc(strlen(line) + 1);
- if (!newo) return gpg_error_from_syserror();
-
- strcpy_escaped(newo, line);
- if (pinentry.ok) free(pinentry.ok);
- pinentry.ok = newo;
- return 0;
-}
-
-static gpg_error_t cmd_setnotok(assuan_context_t ctx, char *line) {
- char *newo;
-
- (void)ctx;
-
- newo = (char *)malloc(strlen(line) + 1);
- if (!newo) return gpg_error_from_syserror();
-
- strcpy_escaped(newo, line);
- if (pinentry.notok) free(pinentry.notok);
- pinentry.notok = newo;
- return 0;
-}
-
-static gpg_error_t cmd_setcancel(assuan_context_t ctx, char *line) {
- char *newc;
-
- (void)ctx;
-
- newc = (char *)malloc(strlen(line) + 1);
- if (!newc) return gpg_error_from_syserror();
-
- strcpy_escaped(newc, line);
- if (pinentry.cancel) free(pinentry.cancel);
- pinentry.cancel = newc;
- return 0;
-}
-
-static gpg_error_t cmd_settimeout(assuan_context_t ctx, char *line) {
- (void)ctx;
-
- if (line && *line) pinentry.timeout = atoi(line);
-
- return 0;
-}
-
-static gpg_error_t cmd_settitle(assuan_context_t ctx, char *line) {
- char *newt;
-
- (void)ctx;
-
- newt = (char *)malloc(strlen(line) + 1);
- if (!newt) return gpg_error_from_syserror();
-
- strcpy_escaped(newt, line);
- if (pinentry.title) free(pinentry.title);
- pinentry.title = newt;
- return 0;
-}
-
-static gpg_error_t cmd_setqualitybar(assuan_context_t ctx, char *line) {
- char *newval;
-
- (void)ctx;
-
- if (!*line) line = "Quality:";
-
- newval = (char *)malloc(strlen(line) + 1);
- if (!newval) return gpg_error_from_syserror();
-
- strcpy_escaped(newval, line);
- if (pinentry.quality_bar) free(pinentry.quality_bar);
- pinentry.quality_bar = newval;
- return 0;
-}
-
-/* Set the tooltip to be used for a quality bar. */
-static gpg_error_t cmd_setqualitybar_tt(assuan_context_t ctx, char *line) {
- char *newval;
-
- (void)ctx;
-
- if (*line) {
- newval = (char *)malloc(strlen(line) + 1);
- if (!newval) return gpg_error_from_syserror();
-
- strcpy_escaped(newval, line);
- } else
- newval = NULL;
- if (pinentry.quality_bar_tt) free(pinentry.quality_bar_tt);
- pinentry.quality_bar_tt = newval;
- return 0;
-}
-
-/* Set the tooltip to be used for a generate action. */
-static gpg_error_t cmd_setgenpin_tt(assuan_context_t ctx, char *line) {
- char *newval;
-
- (void)ctx;
-
- if (*line) {
- newval = (char *)malloc(strlen(line) + 1);
- if (!newval) return gpg_error_from_syserror();
-
- strcpy_escaped(newval, line);
- } else
- newval = NULL;
- if (pinentry.genpin_tt) free(pinentry.genpin_tt);
- pinentry.genpin_tt = newval;
- return 0;
-}
-
-/* Set the label to be used for a generate action. */
-static gpg_error_t cmd_setgenpin_label(assuan_context_t ctx, char *line) {
- char *newval;
-
- (void)ctx;
-
- if (*line) {
- newval = (char *)malloc(strlen(line) + 1);
- if (!newval) return gpg_error_from_syserror();
-
- strcpy_escaped(newval, line);
- } else
- newval = NULL;
- if (pinentry.genpin_label) free(pinentry.genpin_label);
- pinentry.genpin_label = newval;
- return 0;
-}
-
-static gpg_error_t cmd_getpin(assuan_context_t ctx, char *line) {
- int result;
- int set_prompt = 0;
- int just_read_password_from_cache = 0;
-
- (void)line;
-
- pinentry_setbuffer_init(&pinentry);
- if (!pinentry.pin) return gpg_error(GPG_ERR_ENOMEM);
-
- pinentry.confirm = 0;
-
- /* Try reading from the password cache. */
- if (/* If repeat passphrase is set, then we don't want to read from
- the cache. */
- !pinentry.repeat_passphrase
- /* Are we allowed to read from the cache? */
- && pinentry.allow_external_password_cache &&
- pinentry.keyinfo
- /* Only read from the cache if we haven't already tried it. */
- && !pinentry.tried_password_cache
- /* If the last read resulted in an error, then don't read from
- the cache. */
- && !pinentry.error) {
- char *password;
- int give_up_on_password_store = 0;
-
- pinentry.tried_password_cache = 1;
-
- password =
- password_cache_lookup(pinentry.keyinfo, &give_up_on_password_store);
- if (give_up_on_password_store) pinentry.allow_external_password_cache = 0;
-
- if (password)
- /* There is a cached password. Try it. */
- {
- int len = strlen(password) + 1;
- if (len > pinentry.pin_len) len = pinentry.pin_len;
-
- memcpy(pinentry.pin, password, len);
- pinentry.pin[len] = '\0';
-
- secmem_free(password);
-
- pinentry.pin_from_cache = 1;
-
- assuan_write_status(ctx, "PASSWORD_FROM_CACHE", "");
-
- /* Result is the length of the password not including the
- NUL terminator. */
- result = len - 1;
-
- just_read_password_from_cache = 1;
-
- goto out;
- }
- }
-
- /* The password was not cached (or we are not allowed to / cannot
- use the cache). Prompt the user. */
- pinentry.pin_from_cache = 0;
-
- if (!pinentry.prompt) {
- pinentry.prompt = const_cast<char *>(
- pinentry.default_prompt ? pinentry.default_prompt : "PIN:");
- set_prompt = 1;
- }
- pinentry.locale_err = 0;
- pinentry.specific_err = 0;
- pinentry.specific_err_loc = NULL;
- free(pinentry.specific_err_info);
- pinentry.specific_err_info = NULL;
- pinentry.close_button = 0;
- pinentry.repeat_okay = 0;
- pinentry.one_button = 0;
- pinentry.ctx_assuan = ctx;
- result = (*pinentry_cmd_handler)(&pinentry);
- pinentry.ctx_assuan = NULL;
- if (pinentry.error) {
- free(pinentry.error);
- pinentry.error = NULL;
- }
- if (pinentry.repeat_passphrase) {
- free(pinentry.repeat_passphrase);
- pinentry.repeat_passphrase = NULL;
- }
- if (set_prompt) pinentry.prompt = NULL;
-
- pinentry.quality_bar = 0; /* Reset it after the command. */
-
- if (pinentry.close_button) assuan_write_status(ctx, "BUTTON_INFO", "close");
-
- if (result < 0) {
- pinentry_setbuffer_clear(&pinentry);
- if (pinentry.specific_err) {
- write_status_error(ctx, &pinentry);
-
- if (gpg_err_code(pinentry.specific_err) == GPG_ERR_FULLY_CANCELED)
- assuan_set_flag(ctx, ASSUAN_FORCE_CLOSE, 1);
-
- return pinentry.specific_err;
- }
- return (pinentry.locale_err ? gpg_error(GPG_ERR_LOCALE_PROBLEM)
- : gpg_error(GPG_ERR_CANCELED));
- }
-
-out:
- if (result) {
- if (pinentry.repeat_okay) assuan_write_status(ctx, "PIN_REPEATED", "");
- assuan_begin_confidential(ctx);
- result = assuan_send_data(ctx, pinentry.pin, strlen(pinentry.pin));
- if (!result) result = assuan_send_data(ctx, NULL, 0);
- assuan_end_confidential(ctx);
-
- if (/* GPG Agent says it's okay. */
- pinentry.allow_external_password_cache &&
- pinentry.keyinfo
- /* We didn't just read it from the cache. */
- && !just_read_password_from_cache
- /* And the user said it's okay. */
- && pinentry.may_cache_password)
- /* Cache the password. */
- password_cache_save(pinentry.keyinfo, pinentry.pin);
- }
-
- pinentry_setbuffer_clear(&pinentry);
-
- return result;
-}
-
-/* Note that the option --one-button is a hack to allow the use of old
- pinentries while the caller is ignoring the result. Given that
- options have never been used or flagged as an error the new option
- is an easy way to enable the messsage mode while not requiring to
- update pinentry or to have the caller test for the message
- command. New applications which are free to require an updated
- pinentry should use MESSAGE instead. */
-static gpg_error_t cmd_confirm(assuan_context_t ctx, char *line) {
- int result;
-
- pinentry.one_button = !!strstr(line, "--one-button");
- pinentry.quality_bar = 0;
- pinentry.close_button = 0;
- pinentry.locale_err = 0;
- pinentry.specific_err = 0;
- pinentry.specific_err_loc = NULL;
- free(pinentry.specific_err_info);
- pinentry.specific_err_info = NULL;
- pinentry.canceled = 0;
- pinentry.confirm = 1;
- pinentry_setbuffer_clear(&pinentry);
- result = (*pinentry_cmd_handler)(&pinentry);
- if (pinentry.error) {
- free(pinentry.error);
- pinentry.error = NULL;
- }
-
- if (pinentry.close_button) assuan_write_status(ctx, "BUTTON_INFO", "close");
-
- if (result > 0) return 0; /* OK */
-
- if (pinentry.specific_err) {
- write_status_error(ctx, &pinentry);
-
- if (gpg_err_code(pinentry.specific_err) == GPG_ERR_FULLY_CANCELED)
- assuan_set_flag(ctx, ASSUAN_FORCE_CLOSE, 1);
-
- return pinentry.specific_err;
- }
-
- if (pinentry.locale_err) return gpg_error(GPG_ERR_LOCALE_PROBLEM);
-
- if (pinentry.one_button) return 0; /* OK */
-
- if (pinentry.canceled) return gpg_error(GPG_ERR_CANCELED);
- return gpg_error(GPG_ERR_NOT_CONFIRMED);
-}
-
-static gpg_error_t cmd_message(assuan_context_t ctx, char *line) {
- (void)line;
-
- return cmd_confirm(ctx, "--one-button");
-}
-
/* Return a staically allocated string with information on the mode,
* uid, and gid of DEVICE. On error "?" is returned if DEVICE is
* NULL, "-" is returned. */
@@ -1565,132 +1012,4 @@ static gpg_error_t cmd_getinfo(assuan_context_t ctx, char *line) {
} else
rc = gpg_error(GPG_ERR_ASS_PARAMETER);
return rc;
-}
-
-/* CLEARPASSPHRASE <cacheid>
-
- Clear the cache passphrase associated with the key identified by
- cacheid.
- */
-static gpg_error_t cmd_clear_passphrase(assuan_context_t ctx, char *line) {
- (void)ctx;
-
- if (!line) return gpg_error(GPG_ERR_ASS_INV_VALUE);
-
- /* Remove leading and trailing white space. */
- while (*line == ' ') line++;
- while (line[strlen(line) - 1] == ' ') line[strlen(line) - 1] = 0;
-
- switch (password_cache_clear(line)) {
- case 1:
- return 0;
- case 0:
- return gpg_error(GPG_ERR_ASS_INV_VALUE);
- default:
- return gpg_error(GPG_ERR_ASS_GENERAL);
- }
-}
-
-/* Tell the assuan library about our commands. */
-static gpg_error_t register_commands(assuan_context_t ctx) {
- static struct {
- const char *name;
- gpg_error_t (*handler)(assuan_context_t, char *line);
- } table[] = {{"SETDESC", cmd_setdesc},
- {"SETPROMPT", cmd_setprompt},
- {"SETKEYINFO", cmd_setkeyinfo},
- {"SETREPEAT", cmd_setrepeat},
- {"SETREPEATERROR", cmd_setrepeaterror},
- {"SETREPEATOK", cmd_setrepeatok},
- {"SETERROR", cmd_seterror},
- {"SETOK", cmd_setok},
- {"SETNOTOK", cmd_setnotok},
- {"SETCANCEL", cmd_setcancel},
- {"GETPIN", cmd_getpin},
- {"CONFIRM", cmd_confirm},
- {"MESSAGE", cmd_message},
- {"SETQUALITYBAR", cmd_setqualitybar},
- {"SETQUALITYBAR_TT", cmd_setqualitybar_tt},
- {"SETGENPIN", cmd_setgenpin_label},
- {"SETGENPIN_TT", cmd_setgenpin_tt},
- {"GETINFO", cmd_getinfo},
- {"SETTITLE", cmd_settitle},
- {"SETTIMEOUT", cmd_settimeout},
- {"CLEARPASSPHRASE", cmd_clear_passphrase},
- {NULL}};
- int i, j;
- gpg_error_t rc;
-
- for (i = j = 0; table[i].name; i++) {
- rc = assuan_register_command(ctx, table[i].name, table[i].handler, NULL);
- if (rc) return rc;
- }
- return 0;
-}
-
-int pinentry_loop2(int infd, int outfd) {
- gpg_error_t rc;
- assuan_fd_t filedes[2];
- assuan_context_t ctx;
-
- /* Extra check to make sure we have dropped privs. */
-#ifndef HAVE_DOSISH_SYSTEM
- if (getuid() != geteuid()) abort();
-#endif
-
- rc = assuan_new(&ctx);
- if (rc) {
- fprintf(stderr, "server context creation failed: %s\n", gpg_strerror(rc));
- return -1;
- }
-
- /* For now we use a simple pipe based server so that we can work
- from scripts. We will later add options to run as a daemon and
- wait for requests on a Unix domain socket. */
- filedes[0] = assuan_fdopen(infd);
- filedes[1] = assuan_fdopen(outfd);
- rc = assuan_init_pipe_server(ctx, filedes);
- if (rc) {
- fprintf(stderr, "%s: failed to initialize the server: %s\n", this_pgmname,
- gpg_strerror(rc));
- return -1;
- }
- rc = register_commands(ctx);
- if (rc) {
- fprintf(stderr, "%s: failed to the register commands with Assuan: %s\n",
- this_pgmname, gpg_strerror(rc));
- return -1;
- }
-
- assuan_register_option_handler(ctx, option_handler);
-#if 0
- assuan_set_log_stream (ctx, stderr);
-#endif
- assuan_register_reset_notify(ctx, pinentry_assuan_reset_handler);
-
- for (;;) {
- rc = assuan_accept(ctx);
- if (rc == -1)
- break;
- else if (rc) {
- fprintf(stderr, "%s: Assuan accept problem: %s\n", this_pgmname,
- gpg_strerror(rc));
- break;
- }
-
- rc = assuan_process(ctx);
- if (rc) {
- fprintf(stderr, "%s: Assuan processing failed: %s\n", this_pgmname,
- gpg_strerror(rc));
- continue;
- }
- }
-
- assuan_release(ctx);
- return 0;
-}
-
-/* Start the pinentry event loop. The program will start to process
- Assuan commands until it is finished or an error occurs. If an
- error occurs, -1 is returned. Otherwise, 0 is returned. */
-int pinentry_loop(void) { return pinentry_loop2(STDIN_FILENO, STDOUT_FILENO); }
+} \ No newline at end of file
diff --git a/src/pinentry/pinentry.h b/src/pinentry/pinentry.h
index aec01946..0c91a24e 100644
--- a/src/pinentry/pinentry.h
+++ b/src/pinentry/pinentry.h
@@ -21,7 +21,7 @@
#ifndef PINENTRY_H
#define PINENTRY_H
-#include "secmem.h"
+#include <cstdint>
#ifdef __cplusplus
extern "C" {
@@ -298,30 +298,19 @@ typedef struct pinentry *pinentry_t;
and 1 otherwise. */
typedef int (*pinentry_cmd_handler_t)(pinentry_t pin);
-/* Start the pinentry event loop. The program will start to process
- Assuan commands until it is finished or an error occurs. If an
- error occurs, -1 is returned and errno indicates the type of an
- error. Otherwise, 0 is returned. */
-int pinentry_loop(void);
-
-/* The same as above but allows to specify the i/o descriptors.
- * infd and outfd will be duplicated in this function so the caller
- * still has to close them if necessary.
- */
-int pinentry_loop2(int infd, int outfd);
-
const char *pinentry_get_pgmname(void);
char *pinentry_get_title(pinentry_t pe);
/* Run a quality inquiry for PASSPHRASE of LENGTH. */
-int pinentry_inq_quality(pinentry_t pin, const char *passphrase, size_t length);
+int pinentry_inq_quality(pinentry_t pin, const char *passphrase,
+ std::size_t length);
/* Run a checkpin inquiry for PASSPHRASE of LENGTH. Returns NULL, if the
passphrase satisfies the constraints. Otherwise, returns a malloced error
string. */
char *pinentry_inq_checkpin(pinentry_t pin, const char *passphrase,
- size_t length);
+ std::size_t length);
/* Run a genpin iquriry. Returns a malloced string or NULL */
char *pinentry_inq_genpin(pinentry_t pin);
@@ -351,9 +340,6 @@ void pinentry_parse_opts(int argc, char *argv[]);
/* Set the optional flag used with getinfo. */
void pinentry_set_flavor_flag(const char *string);
-/* The caller must define this variable to process assuan commands. */
-extern pinentry_cmd_handler_t pinentry_cmd_handler;
-
#ifdef WINDOWS
/* Windows declares sleep as obsolete, but provides a definition for
_sleep but non for the still existing sleep. */
diff --git a/src/pinentry/pinentry_main.cpp b/src/pinentry/pinentry_main.cpp
deleted file mode 100644
index fcea7c31..00000000
--- a/src/pinentry/pinentry_main.cpp
+++ /dev/null
@@ -1,413 +0,0 @@
-/* main.cpp - A Qt dialog for PIN entry.
- * Copyright (C) 2002, 2008 Klarälvdalens Datakonsult AB (KDAB)
- * Copyright (C) 2003, 2021 g10 Code GmbH
- * Copyright 2007 Ingo Klöcker
- *
- * Written by Steffen Hansen <[email protected]>.
- * Modified by Marcus Brinkmann <[email protected]>.
- * Modified by Marc Mutz <[email protected]>
- * Software engineering by Ingo Klöcker <[email protected]>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <QApplication>
-#include <QDebug>
-#include <QIcon>
-#include <QMessageBox>
-#include <QPushButton>
-#include <QString>
-#include <QWidget>
-
-#include "accessibility.h"
-#include "keyboardfocusindication.h"
-#include "pinentry.h"
-#include "pinentryconfirm.h"
-#include "pinentrydialog.h"
-#include "util.h"
-#if QT_VERSION >= 0x050000
-#include <QWindow>
-#endif
-
-#include <errno.h>
-#include <gpg-error.h>
-#include <stdio.h>
-
-#include <stdexcept>
-
-#ifdef FALLBACK_CURSES
-#include <pinentry-curses.h>
-#endif
-
-#if QT_VERSION >= 0x050000 && defined(QT_STATIC)
-#include <QtPlugin>
-#ifdef Q_OS_WIN
-#include <shlobj.h>
-#include <windows.h>
-Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
-#elif defined(Q_OS_MAC)
-Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)
-#else
-Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
-#endif
-#endif
-
-#ifdef Q_OS_WIN
-#include <windows.h>
-#endif
-
-#include "pinentry_debug.h"
-
-static QString escape_accel(const QString &s) {
- QString result;
- result.reserve(s.size());
-
- bool afterUnderscore = false;
-
- for (unsigned int i = 0, end = s.size(); i != end; ++i) {
- const QChar ch = s[i];
- if (ch == QLatin1Char('_')) {
- if (afterUnderscore) { // escaped _
- result += QLatin1Char('_');
- afterUnderscore = false;
- } else { // accel
- afterUnderscore = true;
- }
- } else {
- if (afterUnderscore || // accel
- ch == QLatin1Char('&')) { // escape & from being interpreted by Qt
- result += QLatin1Char('&');
- }
- result += ch;
- afterUnderscore = false;
- }
- }
-
- if (afterUnderscore)
- // trailing single underscore: shouldn't happen, but deal with it robustly:
- {
- result += QLatin1Char('_');
- }
-
- return result;
-}
-
-namespace {
-class InvalidUtf8 : public std::invalid_argument {
- public:
- InvalidUtf8() : std::invalid_argument("invalid utf8") {}
- ~InvalidUtf8() throw() {}
-};
-} // namespace
-
-static const bool GPG_AGENT_IS_PORTED_TO_ONLY_SEND_UTF8 = false;
-
-static QString from_utf8(const char *s) {
- const QString result = QString::fromUtf8(s);
- if (result.contains(QChar::ReplacementCharacter)) {
- if (GPG_AGENT_IS_PORTED_TO_ONLY_SEND_UTF8) {
- throw InvalidUtf8();
- } else {
- return QString::fromLocal8Bit(s);
- }
- }
-
- return result;
-}
-
-static void setup_foreground_window(QWidget *widget, WId parentWid) {
-#if QT_VERSION >= 0x050000
- /* For windows set the desktop window as the transient parent */
- QWindow *parentWindow = nullptr;
- if (parentWid) {
- parentWindow = QWindow::fromWinId(parentWid);
- }
-#ifdef Q_OS_WIN
- if (!parentWindow) {
- HWND desktop = GetDesktopWindow();
- if (desktop) {
- parentWindow = QWindow::fromWinId((WId)desktop);
- }
- }
-#endif
- if (parentWindow) {
- // Ensure that we have a native wid
- widget->winId();
- QWindow *wndHandle = widget->windowHandle();
-
- if (wndHandle) {
- wndHandle->setTransientParent(parentWindow);
- }
- }
-#endif
- widget->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint |
- Qt::WindowTitleHint | Qt::WindowCloseButtonHint |
- Qt::WindowStaysOnTopHint |
- Qt::WindowMinimizeButtonHint);
-}
-
-static int qt_cmd_handler(pinentry_t pe) {
- int want_pass = !!pe->pin;
-
- const QString ok = pe->ok ? escape_accel(from_utf8(pe->ok))
- : pe->default_ok ? escape_accel(from_utf8(pe->default_ok))
- :
- /* else */ QLatin1String("&OK");
- const QString cancel = pe->cancel ? escape_accel(from_utf8(pe->cancel))
- : pe->default_cancel
- ? escape_accel(from_utf8(pe->default_cancel))
- :
- /* else */ QLatin1String("&Cancel");
-
- unique_malloced_ptr<char> str{pinentry_get_title(pe)};
- const QString title = str ? from_utf8(str.get()) :
- /* else */ QLatin1String("pinentry-qt");
-
- const QString repeatError = pe->repeat_error_string
- ? from_utf8(pe->repeat_error_string)
- : QLatin1String("Passphrases do not match");
- const QString repeatString =
- pe->repeat_passphrase ? from_utf8(pe->repeat_passphrase) : QString();
- const QString visibilityTT = pe->default_tt_visi
- ? from_utf8(pe->default_tt_visi)
- : QLatin1String("Show passphrase");
- const QString hideTT = pe->default_tt_hide ? from_utf8(pe->default_tt_hide)
- : QLatin1String("Hide passphrase");
-
- const QString capsLockHint = pe->default_capshint
- ? from_utf8(pe->default_capshint)
- : QLatin1String("Caps Lock is on");
-
- const QString generateLbl =
- pe->genpin_label ? from_utf8(pe->genpin_label) : QString();
- const QString generateTT =
- pe->genpin_tt ? from_utf8(pe->genpin_tt) : QString();
-
- if (want_pass) {
- PinEntryDialog pinentry(nullptr, 0, pe->timeout, true, !!pe->quality_bar,
- repeatString, visibilityTT, hideTT);
- setup_foreground_window(&pinentry, pe->parent_wid);
- pinentry.setPinentryInfo(pe);
- pinentry.setPrompt(escape_accel(from_utf8(pe->prompt)));
- pinentry.setDescription(from_utf8(pe->description));
- pinentry.setRepeatErrorText(repeatError);
- pinentry.setGenpinLabel(generateLbl);
- pinentry.setGenpinTT(generateTT);
- pinentry.setCapsLockHint(capsLockHint);
- pinentry.setFormattedPassphrase({bool(pe->formatted_passphrase),
- from_utf8(pe->formatted_passphrase_hint)});
- pinentry.setConstraintsOptions({bool(pe->constraints_enforce),
- from_utf8(pe->constraints_hint_short),
- from_utf8(pe->constraints_hint_long),
- from_utf8(pe->constraints_error_title)});
-
- if (!title.isEmpty()) {
- pinentry.setWindowTitle(title);
- }
-
- /* If we reuse the same dialog window. */
- pinentry.setPin(QString());
-
- pinentry.setOkText(ok);
- pinentry.setCancelText(cancel);
- if (pe->error) {
- pinentry.setError(from_utf8(pe->error));
- }
- if (pe->quality_bar) {
- pinentry.setQualityBar(from_utf8(pe->quality_bar));
- }
- if (pe->quality_bar_tt) {
- pinentry.setQualityBarTT(from_utf8(pe->quality_bar_tt));
- }
- bool ret = pinentry.exec();
- if (!ret) {
- if (pinentry.timedOut()) pe->specific_err = gpg_error(GPG_ERR_TIMEOUT);
- return -1;
- }
-
- const QString pinStr = pinentry.pin();
- QByteArray pin = pinStr.toUtf8();
-
- if (!!pe->repeat_passphrase) {
- /* Should not have been possible to accept
- the dialog in that case but we do a safety
- check here */
- pe->repeat_okay = (pinStr == pinentry.repeatedPin());
- }
-
- int len = strlen(pin.constData());
- if (len >= 0) {
- pinentry_setbufferlen(pe, len + 1);
- if (pe->pin) {
- strcpy(pe->pin, pin.constData());
- return len;
- }
- }
- return -1;
- } else {
- const QString desc =
- pe->description ? from_utf8(pe->description) : QString();
- const QString notok =
- pe->notok ? escape_accel(from_utf8(pe->notok)) : QString();
-
- const QMessageBox::StandardButtons buttons =
- pe->one_button ? QMessageBox::Ok
- : pe->notok ? QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel
- :
- /* else */ QMessageBox::Ok | QMessageBox::Cancel;
-
- PinentryConfirm box{QMessageBox::Information, title, desc, buttons};
- box.setTextFormat(Qt::PlainText);
- box.setTextInteractionFlags(Qt::TextSelectableByMouse);
- box.setTimeout(std::chrono::seconds{pe->timeout});
- setup_foreground_window(&box, pe->parent_wid);
-
- const struct {
- QMessageBox::StandardButton button;
- QString label;
- } buttonLabels[] = {
- {QMessageBox::Ok, ok},
- {QMessageBox::Yes, ok},
- {QMessageBox::No, notok},
- {QMessageBox::Cancel, cancel},
- };
-
- for (size_t i = 0; i < sizeof buttonLabels / sizeof *buttonLabels; ++i)
- if ((buttons & buttonLabels[i].button) &&
- !buttonLabels[i].label.isEmpty()) {
- box.button(buttonLabels[i].button)->setText(buttonLabels[i].label);
- Accessibility::setDescription(box.button(buttonLabels[i].button),
- buttonLabels[i].label);
- }
-
- box.setIconPixmap(applicationIconPixmap());
-
- if (!pe->one_button) {
- box.setDefaultButton(QMessageBox::Cancel);
- }
-
- box.show();
- raiseWindow(&box);
-
- const int rc = box.exec();
-
- if (rc == QMessageBox::Cancel) {
- pe->canceled = true;
- }
- if (box.timedOut()) {
- pe->specific_err = gpg_error(GPG_ERR_TIMEOUT);
- }
-
- return rc == QMessageBox::Ok || rc == QMessageBox::Yes;
- }
-}
-
-static int qt_cmd_handler_ex(pinentry_t pe) {
- try {
- return qt_cmd_handler(pe);
- } catch (const InvalidUtf8 &) {
- pe->locale_err = true;
- return pe->pin ? -1 : false;
- } catch (...) {
- pe->canceled = true;
- return pe->pin ? -1 : false;
- }
-}
-
-pinentry_cmd_handler_t pinentry_cmd_handler = qt_cmd_handler_ex;
-
-int pinentry_main(int argc, char *argv[]) {
- pinentry_init("pinentry-qt");
-
- QApplication *app = NULL;
- int new_argc = 0;
-
-#ifdef FALLBACK_CURSES
-#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
- // check a few environment variables that are usually set on X11 or Wayland
- // sessions
- const bool hasWaylandDisplay = qEnvironmentVariableIsSet("WAYLAND_DISPLAY");
- const bool isWaylandSessionType = qgetenv("XDG_SESSION_TYPE") == "wayland";
- const bool hasX11Display = pinentry_have_display(argc, argv);
- const bool isX11SessionType = qgetenv("XDG_SESSION_TYPE") == "x11";
- const bool isGUISession = hasWaylandDisplay || isWaylandSessionType ||
- hasX11Display || isX11SessionType;
- qCDebug(PINENTRY_LOG) << "hasWaylandDisplay:" << hasWaylandDisplay;
- qCDebug(PINENTRY_LOG) << "isWaylandSessionType:" << isWaylandSessionType;
- qCDebug(PINENTRY_LOG) << "hasX11Display:" << hasX11Display;
- qCDebug(PINENTRY_LOG) << "isX11SessionType:" << isX11SessionType;
- qCDebug(PINENTRY_LOG) << "isGUISession:" << isGUISession;
-#else
- const bool isGUISession = pinentry_have_display(argc, argv);
-#endif
- if (!isGUISession) {
- pinentry_cmd_handler = curses_cmd_handler;
- pinentry_set_flavor_flag("curses");
- } else
-#endif
- {
- /* Qt does only understand -display but not --display; thus we
- are fixing that here. The code is pretty simply and may get
- confused if an argument is called "--display". */
- char **new_argv, *p;
- size_t n;
- int i, done;
-
- for (n = 0, i = 0; i < argc; i++) {
- n += strlen(argv[i]) + 1;
- }
- n++;
- new_argv = (char **)calloc(argc + 1, sizeof *new_argv);
- if (new_argv) {
- *new_argv = (char *)malloc(n);
- }
- if (!new_argv || !*new_argv) {
- fprintf(stderr, "pinentry-qt: can't fixup argument list: %s\n",
- strerror(errno));
- exit(EXIT_FAILURE);
- }
- for (done = 0, p = *new_argv, i = 0; i < argc; i++)
- if (!done && !strcmp(argv[i], "--display")) {
- new_argv[i] = strcpy(p, argv[i] + 1);
- p += strlen(argv[i] + 1) + 1;
- done = 1;
- } else {
- new_argv[i] = strcpy(p, argv[i]);
- p += strlen(argv[i]) + 1;
- }
-
- /* Note: QApplication uses int &argc so argc has to be valid
- * for the full lifetime of the application.
- *
- * As Qt might modify argc / argv we use copies here so that
- * we do not loose options that are handled in both. e.g. display.
- */
- new_argc = argc;
- Q_ASSERT(new_argc);
- app = new QApplication(new_argc, new_argv);
- app->setWindowIcon(QIcon(QLatin1String(":/document-encrypt.png")));
- (void)new KeyboardFocusIndication{app};
- }
-
- pinentry_parse_opts(argc, argv);
-
- int rc = pinentry_loop();
- delete app;
- return rc ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/pinentry/pinentrydialog.cpp b/src/pinentry/pinentrydialog.cpp
index f0fba73c..cbd8e891 100644
--- a/src/pinentry/pinentrydialog.cpp
+++ b/src/pinentry/pinentrydialog.cpp
@@ -24,6 +24,8 @@
*/
#include <qnamespace.h>
+
+#include "pinentry.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -504,7 +506,8 @@ void PinEntryDialog::updateQuality(const QString &txt) {
const QByteArray utf8_pin = txt.toUtf8();
const char *pin = utf8_pin.constData();
length = strlen(pin);
- percent = length ? pinentry_inq_quality(_pinentry_info, pin, length) : 0;
+ percent =
+ length ? pinentry_inq_quality(_pinentry_info.get(), pin, length) : 0;
if (!length) {
_quality_bar->reset();
} else {
@@ -521,7 +524,7 @@ void PinEntryDialog::updateQuality(const QString &txt) {
}
void PinEntryDialog::setPinentryInfo(pinentry_t peinfo) {
- _pinentry_info = peinfo;
+ _pinentry_info = std::unique_ptr<struct pinentry>(peinfo);
}
void PinEntryDialog::focusChanged(QWidget *old, QWidget *now) {
@@ -557,7 +560,7 @@ void PinEntryDialog::textChanged(const QString &text) {
}
void PinEntryDialog::generatePin() {
- unique_malloced_ptr<char> pin{pinentry_inq_genpin(_pinentry_info)};
+ unique_malloced_ptr<char> pin{pinentry_inq_genpin(_pinentry_info.get())};
if (pin) {
if (_edit->echoMode() == QLineEdit::Password) {
if (mVisiActionEdit) {
@@ -685,7 +688,7 @@ PinEntryDialog::PassphraseCheckResult PinEntryDialog::checkConstraints() {
const auto passphrase = _edit->pin().toUtf8();
unique_malloced_ptr<char> error{pinentry_inq_checkpin(
- _pinentry_info, passphrase.constData(), passphrase.size())};
+ _pinentry_info.get(), passphrase.constData(), passphrase.size())};
if (!error) {
return PassphraseOk;
diff --git a/src/pinentry/pinentrydialog.h b/src/pinentry/pinentrydialog.h
index 97a90478..def61d20 100644
--- a/src/pinentry/pinentrydialog.h
+++ b/src/pinentry/pinentrydialog.h
@@ -30,6 +30,7 @@
#include <QDialog>
#include <QStyle>
#include <QTimer>
+#include <memory>
#include "pinentry.h"
@@ -163,7 +164,8 @@ class PinEntryDialog : public QDialog
bool _disable_echo_allowed = true;
bool mEnforceConstraints = false;
bool mFormatPassphrase = false;
- pinentry_t _pinentry_info = nullptr;
+ std::unique_ptr<struct pinentry> _pinentry_info =
+ std::make_unique<struct pinentry>();
QTimer *_timer = nullptr;
QString mVisibilityTT;
QString mHideTT;
diff --git a/src/pinentry/pinlineedit.h b/src/pinentry/pinlineedit.h
index e67ced83..e8a3ca0f 100644
--- a/src/pinentry/pinlineedit.h
+++ b/src/pinentry/pinlineedit.h
@@ -23,41 +23,39 @@
#define _PINLINEEDIT_H_
#include <QLineEdit>
-
#include <memory>
-class PinLineEdit : public QLineEdit
-{
- Q_OBJECT
+class PinLineEdit : public QLineEdit {
+ Q_OBJECT
-public:
- explicit PinLineEdit(QWidget *parent = nullptr);
- ~PinLineEdit() override;
+ public:
+ explicit PinLineEdit(QWidget *parent = nullptr);
+ ~PinLineEdit() override;
- void setPin(const QString &pin);
- QString pin() const;
+ void setPin(const QString &pin);
+ QString pin() const;
-public Q_SLOTS:
- void setFormattedPassphrase(bool on);
- void copy() const;
- void cut();
+ public Q_SLOTS:
+ void setFormattedPassphrase(bool on);
+ void copy() const;
+ void cut();
-Q_SIGNALS:
- void backspacePressed();
+ Q_SIGNALS:
+ void backspacePressed();
-protected:
- void keyPressEvent(QKeyEvent *) override;
+ protected:
+ void keyPressEvent(QKeyEvent *) override;
-private:
- using QLineEdit::setText;
- using QLineEdit::text;
+ private:
+ using QLineEdit::setText;
+ using QLineEdit::text;
-private Q_SLOTS:
- void textEdited();
+ private Q_SLOTS:
+ void textEdited();
-private:
- class Private;
- std::unique_ptr<Private> d;
+ private:
+ class Private;
+ std::unique_ptr<Private> d;
};
-#endif // _PINLINEEDIT_H_
+#endif // _PINLINEEDIT_H_
diff --git a/src/pinentry/secmem.cpp b/src/pinentry/secmem.cpp
deleted file mode 100644
index cb4eeb4f..00000000
--- a/src/pinentry/secmem.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-/* secmem.c - memory allocation from a secure heap
- * Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc.
- * Copyright (C) 2015 g10 Code GmbH
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WINDOWS
-#include <errno.h>
-#endif
-#include <stdarg.h>
-#include <unistd.h>
-#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#endif
-#include <string.h>
-
-#include "secmem.h"
-
-#ifdef ORIGINAL_GPG_VERSION
-#include "types.h"
-#include "util.h"
-#else /* ORIGINAL_GPG_VERSION */
-
-#include "secmem_util.h"
-
-typedef union {
- int a;
- short b;
- char c[1];
- long d;
-#ifdef HAVE_U64_TYPE
- u64 e;
-#endif
- float f;
- double g;
-} PROPERLY_ALIGNED_TYPE;
-
-#define log_error log_info
-#define log_bug log_fatal
-
-void log_info(char *template_, ...) {
- va_list args;
-
- va_start(args, template_);
- vfprintf(stderr, template_, args);
- va_end(args);
-}
-
-void log_fatal(char *template_, ...) {
- va_list args;
-
- va_start(args, template_);
- vfprintf(stderr, template_, args);
- va_end(args);
- exit(EXIT_FAILURE);
-}
-
-#endif /* ORIGINAL_GPG_VERSION */
-
-#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-#define DEFAULT_POOLSIZE 16384
-
-typedef struct memblock_struct MEMBLOCK;
-struct memblock_struct {
- unsigned size;
- union {
- MEMBLOCK *next;
- PROPERLY_ALIGNED_TYPE aligned;
- } u;
-};
-
-static void *pool;
-static volatile int pool_okay; /* may be checked in an atexit function */
-#if HAVE_MMAP
-static int pool_is_mmapped;
-#endif
-static size_t poolsize; /* allocated length */
-static size_t poollen; /* used length */
-static MEMBLOCK *unused_blocks;
-static unsigned max_alloced;
-static unsigned cur_alloced;
-static unsigned max_blocks;
-static unsigned cur_blocks;
-static int disable_secmem;
-static int show_warning;
-static int no_warning;
-static int suspend_warning;
-
-static void print_warn(void) {
- if (!no_warning) log_info("Warning: using insecure memory!\n");
-}
-
-static void lock_pool(void *p, size_t n) {
-#if defined(HAVE_MLOCK)
- uid_t uid;
- int err;
-
- uid = getuid();
-
-#ifdef HAVE_BROKEN_MLOCK
- if (uid) {
- errno = EPERM;
- err = -1;
- } else {
- err = mlock(p, n);
- }
-#else
- err = mlock(p, n);
-#endif
-
- if (uid && !geteuid()) {
- if (setuid(uid) || getuid() != geteuid())
- log_fatal("failed to reset uid: %s\n", strerror(errno));
- }
-
- if (err) {
- if (errno != EPERM
-#ifdef EAGAIN /* OpenBSD returns this */
- && errno != EAGAIN
-#endif
- )
- log_error("can't lock memory: %s\n", strerror(errno));
- show_warning = 1;
- }
-
-#else
- (void)p;
- (void)n;
- log_info("Please note that you don't have secure memory on this system\n");
-#endif
-}
-
-static void init_pool(size_t n) {
-#if HAVE_MMAP
- size_t pgsize;
-#endif
-
- poolsize = n;
-
- if (disable_secmem) log_bug("secure memory is disabled");
-
-#if HAVE_MMAP
-#ifdef HAVE_GETPAGESIZE
- pgsize = getpagesize();
-#else
- pgsize = 4096;
-#endif
-
- poolsize = (poolsize + pgsize - 1) & ~(pgsize - 1);
-#ifdef MAP_ANONYMOUS
- pool = mmap(0, poolsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0);
-#else /* map /dev/zero instead */
- {
- int fd;
-
- fd = open("/dev/zero", O_RDWR);
- if (fd == -1) {
- log_error("can't open /dev/zero: %s\n", strerror(errno));
- pool = (void *)-1;
- } else {
- pool = mmap(0, poolsize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- close(fd);
- }
- }
-#endif
- if (pool == (void *)-1)
- log_info("can't mmap pool of %u bytes: %s - using malloc\n",
- (unsigned)poolsize, strerror(errno));
- else {
- pool_is_mmapped = 1;
- pool_okay = 1;
- }
-
-#endif
- if (!pool_okay) {
- pool = malloc(poolsize);
- if (!pool)
- log_fatal("can't allocate memory pool of %u bytes\n", (unsigned)poolsize);
- else
- pool_okay = 1;
- }
- lock_pool(pool, poolsize);
- poollen = 0;
-}
-
-/* concatenate unused blocks */
-static void compress_pool(void) { /* fixme: we really should do this */
-}
-
-void secmem_set_flags(unsigned flags) {
- int was_susp = suspend_warning;
-
- no_warning = flags & 1;
- suspend_warning = flags & 2;
-
- /* and now issue the warning if it is not longer suspended */
- if (was_susp && !suspend_warning && show_warning) {
- show_warning = 0;
- print_warn();
- }
-}
-
-unsigned secmem_get_flags(void) {
- unsigned flags;
-
- flags = no_warning ? 1 : 0;
- flags |= suspend_warning ? 2 : 0;
- return flags;
-}
-
-void secmem_init(size_t n) {
- if (!n) {
-#if !defined(HAVE_DOSISH_SYSTEM)
- uid_t uid;
-
- disable_secmem = 1;
- uid = getuid();
- if (uid != geteuid()) {
- if (setuid(uid) || getuid() != geteuid())
- log_fatal("failed to drop setuid\n");
- }
-#endif
- } else {
- if (n < DEFAULT_POOLSIZE) n = DEFAULT_POOLSIZE;
- if (!pool_okay)
- init_pool(n);
- else
- log_error("Oops, secure memory pool already initialized\n");
- }
-}
-
-void *secmem_malloc(size_t size) {
- MEMBLOCK *mb, *mb2;
- int compressed = 0;
-
- if (!pool_okay) {
- log_info("operation is not possible without initialized secure memory\n");
- log_info("(you may have used the wrong program for this task)\n");
- exit(2);
- }
- if (show_warning && !suspend_warning) {
- show_warning = 0;
- print_warn();
- }
-
- /* blocks are always a multiple of 32 */
- size += sizeof(MEMBLOCK);
- size = ((size + 31) / 32) * 32;
-
-retry:
- /* try to get it from the used blocks */
- for (mb = unused_blocks, mb2 = NULL; mb; mb2 = mb, mb = mb->u.next)
- if (mb->size >= size) {
- if (mb2)
- mb2->u.next = mb->u.next;
- else
- unused_blocks = mb->u.next;
- goto leave;
- }
- /* allocate a new block */
- if ((poollen + size <= poolsize)) {
- mb = (MEMBLOCK *)((char *)pool + poollen);
- poollen += size;
- mb->size = size;
- } else if (!compressed) {
- compressed = 1;
- compress_pool();
- goto retry;
- } else
- return NULL;
-
-leave:
- cur_alloced += mb->size;
- cur_blocks++;
- if (cur_alloced > max_alloced) max_alloced = cur_alloced;
- if (cur_blocks > max_blocks) max_blocks = cur_blocks;
-
- memset(&mb->u.aligned.c, 0,
- size - (size_t) & ((struct memblock_struct *)0)->u.aligned.c);
-
- return &mb->u.aligned.c;
-}
-
-void *secmem_realloc(void *p, size_t newsize) {
- MEMBLOCK *mb;
- size_t size;
- void *a;
-
- if (!p) return secmem_malloc(newsize);
-
- mb = (MEMBLOCK *)(void *)((char *)p - offsetof(MEMBLOCK, u.aligned.c));
-
- size = mb->size;
- if (newsize < size) return p; /* it is easier not to shrink the memory */
- a = secmem_malloc(newsize);
- memcpy(a, p, size);
- memset((char *)a + size, 0, newsize - size);
- secmem_free(p);
- return a;
-}
-
-void secmem_free(void *a) {
- MEMBLOCK *mb;
- size_t size;
-
- if (!a) return;
-
- mb = (MEMBLOCK *)(void *)((char *)a - offsetof(MEMBLOCK, u.aligned.c));
- size = mb->size;
- /* This does not make much sense: probably this memory is held in the
- * cache. We do it anyway: */
- wipememory2(mb, 0xff, size);
- wipememory2(mb, 0xaa, size);
- wipememory2(mb, 0x55, size);
- wipememory2(mb, 0x00, size);
- mb->size = size;
- mb->u.next = unused_blocks;
- unused_blocks = mb;
- cur_blocks--;
- cur_alloced -= size;
-}
-
-int m_is_secure(const void *p) {
- return p >= pool && p < (void *)((char *)pool + poolsize);
-}
-
-void secmem_term(void) {
- if (!pool_okay) return;
-
- wipememory2(pool, 0xff, poolsize);
- wipememory2(pool, 0xaa, poolsize);
- wipememory2(pool, 0x55, poolsize);
- wipememory2(pool, 0x00, poolsize);
-#if HAVE_MMAP
- if (pool_is_mmapped) munmap(pool, poolsize);
-#endif
- pool = NULL;
- pool_okay = 0;
- poolsize = 0;
- poollen = 0;
- unused_blocks = NULL;
-}
-
-void secmem_dump_stats(void) {
- if (disable_secmem) return;
- fprintf(stderr, "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n",
- cur_alloced, max_alloced, cur_blocks, max_blocks, (ulong)poollen,
- (ulong)poolsize);
-}
-
-size_t secmem_get_max_size(void) { return poolsize; }
diff --git a/src/pinentry/secmem.h b/src/pinentry/secmem.h
deleted file mode 100644
index 75fe708b..00000000
--- a/src/pinentry/secmem.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Quintuple Agent secure memory allocation
- * Copyright (C) 1998,1999 Free Software Foundation, Inc.
- * Copyright (C) 1999,2000 Robert Bihlmeyer <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef _MEMORY_H
-#define _MEMORY_H
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#if 0
-}
-#endif
-#endif
-
-
-/* values for flags, hardcoded in secmem.c */
-#define SECMEM_WARN 0
-#define SECMEM_DONT_WARN 1
-#define SECMEM_SUSPEND_WARN 2
-
-void secmem_init( size_t npool );
-void secmem_term( void );
-void *secmem_malloc( size_t size );
-void *secmem_realloc( void *a, size_t newsize );
-void secmem_free( void *a );
-int m_is_secure( const void *p );
-void secmem_dump_stats(void);
-void secmem_set_flags( unsigned flags );
-unsigned secmem_get_flags(void);
-size_t secmem_get_max_size (void);
-
-#if 0
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif /* _MEMORY_H */
diff --git a/src/pinentry/secmem_util.h b/src/pinentry/secmem_util.h
deleted file mode 100644
index 3c8ffb8a..00000000
--- a/src/pinentry/secmem_util.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Quintuple Agent utilities
- * Copyright (C) 1999 Robert Bihlmeyer <[email protected]>
- * Copyright (C) 2003 g10 Code GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef _UTIL_H
-#define _UTIL_H
-
-#include <sys/types.h>
-
-#ifndef HAVE_TYPE_BYTE
-# undef byte
-# if !(defined(_WIN32) && defined(cbNDRContext))
- /* Windows typedefs byte in the rpc headers. Avoid warning about
- double definition. */
- typedef unsigned char byte;
-# endif
-# define HAVE_TYPE_BYTE
-#endif
-
-#ifndef HAVE_TYPE_ULONG
-# undef ulong
- typedef unsigned long ulong;
-# define HAVE_TYPE_ULONG
-#endif
-
-
-ssize_t xwrite(int, const void *, size_t); /* write until finished */
-int debugmsg(const char *, ...); /* output a debug message if debugging==on */
-void drop_privs(void); /* finally drop privileges */
-
-
-/* To avoid that a compiler optimizes certain memset calls away, these
- macros may be used instead. */
-#define wipememory2(_ptr,_set,_len) do { \
- volatile char *_vptr=(volatile char *)(_ptr); \
- size_t _vlen=(_len); \
- while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
- } while(0)
-#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
-#define wipe(_ptr,_len) wipememory2(_ptr,0,_len)
-
-
-
-
-#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
- *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
-#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-
-
-#endif
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 0006738c..06bea61a 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -50,15 +50,18 @@ generate_export_header(gpgfrontend_ui EXPORT_FILE_NAME "${_export_file}")
# link Qt
if(Qt6_DIR)
target_link_libraries(gpgfrontend_ui
- Qt6::Network Qt6::PrintSupport Qt6::Widgets Qt6::Test Qt6::Core5Compat Qt6::Core)
+ Qt6::Network Qt6::PrintSupport Qt6::Test Qt6::Core5Compat)
else()
target_link_libraries(gpgfrontend_ui
- Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core)
+ Qt5::Network Qt5::PrintSupport Qt5::Test)
endif()
# link gpgfrontend_core
target_link_libraries(gpgfrontend_ui gpgfrontend_core)
+# link buddled pinentry
+target_link_libraries(gpgfrontend_ui gpgfrontend_pinentry)
+
# set up pch
target_precompile_headers(gpgfrontend_ui PUBLIC GpgFrontendUI.h)
diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp
index 2e3596f8..dabdf657 100644
--- a/src/ui/UserInterfaceUtils.cpp
+++ b/src/ui/UserInterfaceUtils.cpp
@@ -43,7 +43,6 @@
#include "core/thread/TaskRunnerGetter.h"
#include "core/utils/CacheUtils.h"
#include "core/utils/IOUtils.h"
-#include "spdlog/spdlog.h"
#include "ui/UISignalStation.h"
#include "ui/dialog/WaitingDialog.h"
#include "ui/dialog/gnupg/GnuPGControllerDialog.h"
diff --git a/src/ui/function/RaisePinentry.cpp b/src/ui/function/RaisePinentry.cpp
new file mode 100644
index 00000000..7ed98b93
--- /dev/null
+++ b/src/ui/function/RaisePinentry.cpp
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "RaisePinentry.h"
+
+#include "core/function/CoreSignalStation.h"
+#include "pinentry/pinentrydialog.h"
+
+namespace GpgFrontend::UI {
+
+RaisePinentry::RaisePinentry(QWidget* parent) : QWidget(parent) {}
+
+auto RaisePinentry::Exec() -> int {
+ auto* pinentry =
+ new PinEntryDialog(this, 0, 0, true, false, QString(),
+ QString::fromStdString(_("Show passphrase")),
+ QString::fromStdString(_("Hide passphrase")));
+
+ SPDLOG_DEBUG("setting pinetry's arguments");
+
+ pinentry->setPinentryInfo(new struct pinentry());
+ pinentry->setPrompt(QString::fromStdString(_("PIN:")));
+ pinentry->setDescription(QString());
+ pinentry->setRepeatErrorText(
+ QString::fromStdString(_("Passphrases do not match")));
+ pinentry->setGenpinLabel(QString());
+ pinentry->setGenpinTT(QString());
+ pinentry->setCapsLockHint(QString::fromStdString(_("Caps Lock is on")));
+ pinentry->setFormattedPassphrase({false, QString()});
+ pinentry->setConstraintsOptions({false, QString(), QString(), QString()});
+
+ pinentry->setWindowTitle(_("Pinentry"));
+
+ /* If we reuse the same dialog window. */
+ pinentry->setPin(QString());
+ pinentry->setOkText(_("Confirm"));
+ pinentry->setCancelText(_("Cancel"));
+
+ SPDLOG_DEBUG("pinentry is ready to start");
+
+ connect(pinentry, &PinEntryDialog::finished, this, [pinentry](int result) {
+ bool ret = result != 0;
+ SPDLOG_DEBUG("PinEntryDialog finished, ret: {}", ret);
+
+ if (!ret) {
+ emit CoreSignalStation::GetInstance()->SignalUserInputPassphraseCallback(
+ {});
+ return -1;
+ }
+
+ auto pin = pinentry->pin().toUtf8();
+ emit CoreSignalStation::GetInstance()->SignalUserInputPassphraseCallback(
+ pin);
+ return 0;
+ });
+
+ pinentry->open();
+}
+} // namespace GpgFrontend::UI
diff --git a/src/ui/function/RaisePinentry.h b/src/ui/function/RaisePinentry.h
new file mode 100644
index 00000000..b950d2b9
--- /dev/null
+++ b/src/ui/function/RaisePinentry.h
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+#include <qwidget.h>
+namespace GpgFrontend::UI {
+
+class RaisePinentry : QWidget {
+ Q_OBJECT
+ public:
+ explicit RaisePinentry(QWidget *parent);
+
+ auto Exec() -> int;
+};
+
+} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/function/SetOwnerTrustLevel.h b/src/ui/function/SetOwnerTrustLevel.h
index ddd7a97f..29cece18 100644
--- a/src/ui/function/SetOwnerTrustLevel.h
+++ b/src/ui/function/SetOwnerTrustLevel.h
@@ -33,6 +33,7 @@
namespace GpgFrontend::UI {
class SetOwnerTrustLevel : public QWidget {
+ Q_OBJECT
public:
/**
* @brief Set the Owner Trust Level object
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index d640d337..65ead3ce 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -33,8 +33,7 @@
#include "core/GpgConstants.h"
#include "core/function/CoreSignalStation.h"
#include "core/function/GlobalSettingStation.h"
-#include "pinentry/pinentrydialog.h"
-#include "spdlog/spdlog.h"
+#include "function/RaisePinentry.h"
#include "ui/UserInterfaceUtils.h"
#include "ui/dialog/Wizard.h"
#include "ui/main_window/KeyMgmt.h"
@@ -230,51 +229,8 @@ void MainWindow::SetCryptoMenuStatus(
}
void MainWindow::SlotRaisePinentry() {
- auto* pinentry =
- new PinEntryDialog(this, 0, 0, true, false, QString(),
- QString::fromStdString(_("Show passphrase")),
- QString::fromStdString(_("Hide passphrase")));
-
- SPDLOG_DEBUG("setting pinetry's arguments");
-
- pinentry->setPinentryInfo(new struct pinentry());
- pinentry->setPrompt(QString::fromStdString(_("PIN:")));
- pinentry->setDescription(QString());
- pinentry->setRepeatErrorText(
- QString::fromStdString(_("Passphrases do not match")));
- pinentry->setGenpinLabel(QString());
- pinentry->setGenpinTT(QString());
- pinentry->setCapsLockHint(QString::fromStdString(_("Caps Lock is on")));
- pinentry->setFormattedPassphrase({false, QString()});
- pinentry->setConstraintsOptions({false, QString(), QString(), QString()});
-
- pinentry->setWindowTitle(_("Pinentry"));
-
- /* If we reuse the same dialog window. */
- pinentry->setPin(QString());
-
- pinentry->setOkText(_("Confirm"));
- pinentry->setCancelText(_("Cancel"));
-
- SPDLOG_DEBUG("pinentry is ready to start");
-
- connect(pinentry, &PinEntryDialog::finished, this, [pinentry](int result) {
- bool ret = result != 0;
- SPDLOG_DEBUG("PinEntryDialog finished, ret: {}", ret);
-
- if (!ret) {
- emit CoreSignalStation::GetInstance()->SignalUserInputPassphraseCallback(
- {});
- return -1;
- }
-
- auto pin = pinentry->pin().toUtf8();
- emit CoreSignalStation::GetInstance()->SignalUserInputPassphraseCallback(
- pin);
- return 0;
- });
-
- pinentry->open();
+ auto function = RaisePinentry(this);
+ function.Exec();
}
} // namespace GpgFrontend::UI
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 829adbf6..0fdc8a16 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -28,4 +28,7 @@
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(json EXCLUDE_FROM_ALL)
-add_subdirectory(spdlog EXCLUDE_FROM_ALL) \ No newline at end of file
+add_subdirectory(spdlog EXCLUDE_FROM_ALL)
+
+set(MI_SECURE ON)
+add_subdirectory(mimalloc EXCLUDE_FROM_ALL) \ No newline at end of file
diff --git a/third_party/mimalloc b/third_party/mimalloc
new file mode 160000
+Subproject 43ce4bd7fd34bcc730c1c7471c9999559741548