- meson should now properly create OpenSSL signing key and hexdump before trying to compile plugin loadermaster
@@ -9,7 +9,6 @@ | |||
#include "aboutdialog.h" | |||
#include "ui_aboutdialog.h" | |||
#include <version.h> | |||
#include "config.h" | |||
// compiler | |||
// clang also defines __GNUC__, so we need to check for clang first |
@@ -7,6 +7,6 @@ about_moc = mod_qt5.preprocess( | |||
dep_about = declare_dependency( | |||
include_directories: include_directories('.'), | |||
link_with: static_library('about', | |||
['aboutdialog.cpp', 'aboutplugin.cpp', about_moc], | |||
dependencies: [dep_qt5, dep_genheaders]) | |||
['aboutdialog.cpp', 'aboutplugin.cpp', about_moc, version_h], | |||
dependencies: [dep_qt5]) | |||
) |
@@ -1,14 +1,13 @@ | |||
configuration_inc = include_directories('.') | |||
configuration_moc = mod_qt5.preprocess( | |||
moc_headers: ['configuration.h'], | |||
dependencies: dep_qt5 | |||
) | |||
configuration_lib = static_library('configuration', ['commandline.cpp', 'configuration.cpp', configuration_moc], | |||
dependencies: [dep_boost, dep_qt5, dep_genheaders] | |||
dependencies: [dep_boost, dep_qt5, autogen_config] | |||
) | |||
dep_configuration = declare_dependency( | |||
include_directories: configuration_inc, | |||
include_directories: include_directories('.'), | |||
link_with: configuration_lib | |||
) |
@@ -1,15 +1,14 @@ | |||
dep_openssl = dependency('openssl') | |||
python = import('python') | |||
python3 = python.find_installation('python3') | |||
openssl_exe = find_program('openssl', required: true) | |||
sh = find_program('sh') | |||
hexdump = meson.source_root() / 'tools/hexdump.py' | |||
private_pem = meson.build_root() / get_option('ssl_private_pem') | |||
public_pem = meson.build_root() / get_option('ssl_public_pem') | |||
publickey = custom_target('publicKey.h', | |||
publicKey_h = custom_target('publicKey_h', | |||
output: 'publicKey.h', | |||
build_by_default: true, | |||
command: [sh, '-c', | |||
openssl_exe.path() + ' genrsa -out privateKey.pem 4096; ' + openssl_exe.path() + ' rsa -in privateKey.pem -pubout -out publicKey.pem; python3 ' + hexdump + ' --name=publicKey_pem publicKey.pem --output=@OUTPUT@' | |||
] | |||
command: [python3, meson.source_root() / 'tools/ssl-keygen.py', | |||
'--private=' + private_pem, '--public=' + public_pem, | |||
'--output=@OUTPUT@', '--array-name=publicKey_pem'] | |||
) | |||
pluginloader_moc = mod_qt5.preprocess( | |||
@@ -20,8 +19,8 @@ pluginloader_moc = mod_qt5.preprocess( | |||
dep_pluginloader = declare_dependency( | |||
include_directories: include_directories('.'), | |||
link_with: static_library('plugin', | |||
['pluginloader.cpp', pluginloader_moc], | |||
['pluginloader.cpp', pluginloader_moc, publicKey_h], | |||
include_directories: include_directories('.'), | |||
dependencies: [dep_qt5, dep_openssl, dep_genheaders]) | |||
dependencies: [dep_qt5]) | |||
) | |||
@@ -6,7 +6,7 @@ pkgdesc='Yet another no-frills browser' | |||
pkgver=r0 | |||
pkgrel=1 | |||
url="https://neueland.iserlohn-fortress.net/smolbote" | |||
url="https://neueland.iserlohn-fortress.net/gitea/smolbote" | |||
install="smolbote.install" | |||
arch=('x86_64') | |||
@@ -17,7 +17,7 @@ optdepends=('firejail: launch a sandboxed instance') | |||
makedepends=('git' 'meson' 'boost' 'python-kconfiglib' 'openssl' 'qt5-tools' 'scdoc' 'spdlog') | |||
# this is the central repository | |||
source=("git+https://neueland.iserlohn-fortress.net/gitea/aeon/smolbote.git" | |||
source=("git+https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote.git" | |||
"git+https://github.com/itay-grudev/SingleApplication.git") | |||
sha512sums=('SKIP' | |||
@@ -32,9 +32,7 @@ sha512sums=('SKIP' | |||
#_menuconfig= | |||
# Enable plugin signing: | |||
# - generate a 4096-bit RSA key and embed the public key into the binary | |||
# - apply the plugin signing patch to the config, enabling PluginLoader::verify | |||
# - sign the plugins with the private key, and install the signatures | |||
# meson/ninja will generate the privateKey.pem and publicKey.pem in the $builddir | |||
# Because this embeds the public key into the executable, enabling this option will break reproducible builds. | |||
_signPlugins= | |||
@@ -44,19 +42,6 @@ prepare() { | |||
git submodule init | |||
git config submodule.3rd-party/SingleApplication/SingleApplication.git.url $srcdir/SingleApplication | |||
git submodule update 3rd-party/SingleApplication/SingleApplication.git | |||
if [ -n $_signPlugins ]; then | |||
msg "Creating OpenSSL signing key" | |||
mkdir $srcdir/signing | |||
cd $srcdir/signing | |||
# generate rsa keypair | |||
openssl genrsa -out privateKey.pem 4096 | |||
msg2 "Keypair written to $srcdir/signing/privateKey.pem." | |||
openssl rsa -in privateKey.pem -pubout -out publicKey.pem | |||
python3 $srcdir/smolbote/tools/hexdump.py --name='publicKey_pem' publicKey.pem --output=$srcdir/smolbote/src/plugin/publicKey.h | |||
msg2 "Public key exported to $srcdir/signing/publicKey.pem." | |||
fi | |||
} | |||
pkgver() { | |||
@@ -104,7 +89,7 @@ package() { | |||
if [ -n $_signPlugins ]; then | |||
msg "Signing plugins" | |||
for so in $pkgdir/usr/local/lib/smolbote/plugins/*.so; do | |||
openssl dgst -sha256 -sign $srcdir/signing/privateKey.pem -out $so.sig $so | |||
openssl dgst -sha256 -sign $srcdir/build/privateKey.pem -out $so.sig $so | |||
# If the sigs were in another location, use | |||
#install -m644 -t $pkgdir/usr/local/lib/smolbote/plugins $so.sig | |||
done |
@@ -2,7 +2,23 @@ project('smolbote', 'cpp', | |||
version: '0.1.0', | |||
default_options: ['cpp_std=c++17', 'strip=true', 'warning_level=3'], | |||
license: 'GPL3', | |||
meson_version: '>=0.49.0' | |||
meson_version: '>=0.51.2' | |||
) | |||
kconfig = import('unstable-kconfig') | |||
cdata = configuration_data(kconfig.load(host_machine.system() + '/.config')) | |||
config_h = configure_file(output: 'config.h', configuration: cdata) | |||
version_h = vcs_tag( | |||
command: [find_program('git').path(), 'describe', '--long', '--abbrev=40'], | |||
#fallback: defaults to meson.project_version(), | |||
input: 'include/version.h.in', | |||
output: 'version.h' | |||
) | |||
autogen_config = declare_dependency( | |||
include_directories: include_directories('.'), | |||
sources: [config_h] | |||
) | |||
# add -DQT_NO_DEBUG to non-debug builds | |||
@@ -27,9 +43,6 @@ add_project_arguments(cxx.get_supported_arguments([ | |||
mod_qt5 = import('qt5') | |||
dep_qt5 = dependency('qt5', modules: ['Core', 'Network', 'Widgets', 'WebEngineWidgets', 'Concurrent']) | |||
mod_python = import('python') | |||
python3 = mod_python.find_installation('python3') | |||
dep_boost = dependency('boost', modules: ['program_options']) | |||
dep_spdlog = dependency('spdlog', fallback: ['spdlog', 'spdlog_dep'], version: '>=1.3.1') | |||
@@ -48,37 +61,11 @@ optional_deps += declare_dependency(compile_args: '-DPLASMA', | |||
) | |||
endif | |||
if get_option('Python').enabled() | |||
optional_deps += declare_dependency(compile_args: '-DPYTHON', | |||
dependencies: [ meson.get_compiler('cpp').find_library('linenoise'), | |||
python3.dependency('python', version: '>=3.0.0')]) | |||
subdir('src/cli') | |||
endif | |||
dep_gtest = dependency('gtest', required: get_option('testing')) | |||
# Generate config header | |||
include = include_directories('include') | |||
git = find_program('git').path() | |||
dep_genheaders = declare_dependency( | |||
include_directories: include_directories('.'), | |||
sources: [ | |||
vcs_tag( | |||
command: [git, 'describe', '--long', '--abbrev=40'], | |||
#fallback: defaults to meson.project_version(), | |||
input: 'include/version.h.in', | |||
output: 'version.h' | |||
), | |||
custom_target('configheader', | |||
input: ['tools/config.py', 'Kconfig', host_machine.system() + '/.config'], | |||
output: 'config.h', | |||
command: [python3, '@INPUT0@', '--kconfig=@INPUT1@', '--dotconfig=@INPUT2@', '--generate=@OUTPUT@'], | |||
build_by_default: true | |||
)] | |||
) | |||
interfaces_moc = mod_qt5.preprocess( | |||
moc_headers: 'include/profileinterface.h', | |||
dependencies: dep_qt5 |
@@ -2,6 +2,11 @@ | |||
option('poiName', description: 'Executable name', type: 'string', value: 'poi') | |||
option('firejail', description: 'firejail executable name', type: 'string', value: '/usr/bin/firejail') | |||
# Build options | |||
option('signPlugins', description: 'Generate OpenSSL signing key', type: 'feature', value: 'auto') | |||
option('ssl_private_pem', description: 'OpenSSL private key path', type: 'string', value: 'privateKey.pem') | |||
option('ssl_public_pem', description: 'OpenSSL public key path', type: 'string', value: 'publicKey.pem') | |||
# Install options | |||
option('manpage', description: 'Generate and install manpage', type: 'feature', value: 'auto') | |||
option('translations', description: 'Generate and install translations', type: 'feature', value: 'auto') |
@@ -118,7 +118,7 @@ QPair<QString, Profile *> Browser::loadProfile(const QString &id, bool isOffTheR | |||
if(h.length() == 2) | |||
interceptor->addHttpHeader(h.at(0).toLatin1(), h.at(1).toLatin1()); | |||
} | |||
profile->setRequestInterceptor(interceptor); | |||
profile->setUrlRequestInterceptor(interceptor); | |||
spdlog::info("Added profile: {}{}", qUtf8Printable(_id), profile->isOffTheRecord() ? " (otr)" : ""); | |||
return QPair<QString, WebProfile *>(_id, profile); |
@@ -13,10 +13,10 @@ poi_moc = mod_qt5.preprocess( | |||
poi = executable(get_option('poiName'), install: true, | |||
cpp_args: ['-DQAPPLICATION_CLASS=QApplication'], | |||
dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_SingleApplication, dep_genheaders, optional_deps, | |||
dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_SingleApplication, optional_deps, | |||
dep_about, dep_addressbar, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, dep_urlfilter, dep_webprofile], | |||
include_directories: [include], | |||
sources: ['main.cpp', 'builtins.cpp', 'crashhandler.cpp', poi_moc, | |||
sources: ['main.cpp', 'builtins.cpp', 'crashhandler.cpp', poi_moc, version_h, | |||
'browser.cpp', | |||
'util.cpp', 'util.h', | |||
@@ -1,20 +0,0 @@ | |||
#!/usr/bin/env python3 | |||
import os | |||
import argparse | |||
import subprocess | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--kconfig", metavar="Kconfig", nargs="?", default="Kconfig", help="Top-level Kconfig file (default: Kconfig)") | |||
parser.add_argument("--dotconfig", metavar="dotconfig", nargs="?", default=".config", help=".config") | |||
parser.add_argument("--generate", metavar="config_header", nargs="?", default="config.h", help="Generate config file") | |||
args = parser.parse_args() | |||
# set srctree, otherwise includes don't work | |||
os.environ["srctree"] = os.path.dirname(os.path.realpath(args.kconfig)) | |||
os.environ["KCONFIG_CONFIG"] = os.path.realpath(args.dotconfig) | |||
subprocess.run(["genconfig", os.path.realpath(args.kconfig), "--header-path=" + args.generate], check=True) | |||
@@ -1,35 +0,0 @@ | |||
#!/usr/bin/env python3 | |||
import argparse | |||
import sys | |||
from functools import partial | |||
parser = argparse.ArgumentParser(description='Convert a file to C array') | |||
parser.add_argument('input', type=str, help='Input file') | |||
parser.add_argument('--output', type=argparse.FileType('wt'), default=sys.stdout, help='Output file') | |||
parser.add_argument('--array-type', type=str, default='const unsigned char', help='Array type') | |||
parser.add_argument('--length-type', type=str, default='const unsigned int', help='Length type') | |||
parser.add_argument('--name', type=str, default='a', help='Array name') | |||
args=parser.parse_args() | |||
print("{} {}[] = {{".format(args.array_type, args.name), file=args.output) | |||
n = 0 | |||
with open(args.input, "rb") as in_file: | |||
for c in iter(partial(in_file.read, 1), b''): | |||
if n % 16 == 0: | |||
print(" ", end='', file=args.output) | |||
print("0x%02X," % ord(c), end='', file=args.output) | |||
n += 1 | |||
if n % 16 == 0: | |||
print("", file=args.output) | |||
else: | |||
print(" ", end='', file=args.output) | |||
print("\n};", file=args.output) | |||
print("{} {}_len = {};".format(args.length_type, args.name, n), file=args.output) | |||
@@ -0,0 +1,59 @@ | |||
#!/usr/bin/env python3 | |||
import argparse | |||
import sys | |||
import os.path | |||
import subprocess | |||
from functools import partial | |||
def generate_private_key(out_pem='privateKey.pem'): | |||
subprocess.run(['openssl', 'genrsa', '-out', out_pem, '4096'], check=True) | |||
def generate_public_key(in_pem='privateKey.pem', out_pem='publicKey.pem'): | |||
subprocess.run(['openssl', 'rsa', '-in', in_pem, '-pubout', '-out', out_pem], check=True) | |||
def hexdump(array_type, array_name, length_type, in_pem, out_h): | |||
n = 0 | |||
print("// Autogenerated hex dump of OpenSSL public key, do not edit", file=out_h) | |||
print("{} {}[] = {{".format(array_type, array_name), file=out_h) | |||
for line in iter(partial(in_pem.read, 16), b''): | |||
l = list(line) | |||
for n, i in enumerate(l): | |||
l[n] = '0x{:02X}'.format(i) | |||
print(" {},".format(", ".join(l)), file=out_h) | |||
n += 1 | |||
print("};", file=out_h) | |||
print("{} {}_len = {};".format(length_type, array_name, n), file=out_h) | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser(description='Generate OpenSSL key and hexdump') | |||
parser.add_argument('--private', default='privateKey.pem', type=str, help='Private key input') | |||
parser.add_argument('--public', default='publicKey.pem', type=str, help='Public key input') | |||
parser.add_argument('--output', type=argparse.FileType('wt'), default=sys.stdout, help='Output file') | |||
parser.add_argument('--array-type', type=str, default='const unsigned char', help='Array type') | |||
parser.add_argument('--length-type', type=str, default='const unsigned int', help='Length type') | |||
parser.add_argument('--array-name', type=str, default='a', help='Array name') | |||
args=parser.parse_args() | |||
# check if public key exists | |||
if not os.path.isfile(args.public): | |||
# if there is no private key, generate one | |||
if not os.path.isfile(args.private): | |||
generate_private_key(args.private) | |||
# export public key from private | |||
generate_public_key(args.private, args.public) | |||
with open(args.public, "rb") as public_pem: | |||
hexdump(args.array_type, args.array_name, args.length_type, public_pem, args.output) | |||