From dd7559561a8a7f4fef7a4bb8b23e2894eca4594c Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Sat, 2 Nov 2019 17:33:28 -0500 Subject: hscript: Add download_file helper and implement SigningKey::execute --- hscript/CMakeLists.txt | 10 +++++++++ hscript/meta.cc | 47 ++++++++++++++++++++++++++++++++++++-- hscript/script.cc | 27 ++++++++++++++++++++++ hscript/util.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ hscript/util.hh | 25 +++++++++++++++++++++ 5 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 hscript/util.cc create mode 100644 hscript/util.hh diff --git a/hscript/CMakeLists.txt b/hscript/CMakeLists.txt index e6e86b6..e7f54e9 100644 --- a/hscript/CMakeLists.txt +++ b/hscript/CMakeLists.txt @@ -1,3 +1,5 @@ +pkg_check_modules(CURL libcurl) + set(HSCRIPT_SOURCE script.cc disk.cc @@ -5,6 +7,7 @@ set(HSCRIPT_SOURCE meta.cc network.cc user.cc + util.cc ) set(HSCRIPT_INCLUDE @@ -14,6 +17,7 @@ set(HSCRIPT_INCLUDE add_library(hscript ${HSCRIPT_SOURCE}) target_compile_features(hscript PRIVATE cxx_nullptr) target_compile_features(hscript PUBLIC cxx_unicode_literals) + if("cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES) set_property(TARGET hscript PROPERTY CXX_STANDARD 17) SET(FS_LIBRARY stdc++fs) @@ -23,7 +27,13 @@ ELSE() SET(FS_LIBRARY ${Boost_FILESYSTEM_LIBRARY}) add_definitions(-DFS_IS_BOOST) ENDIF() + target_link_libraries(hscript ${BLKID_LIBRARIES} ${FS_LIBRARY} ${LIBUDEV_LIBRARIES} ${PARTED_LIBRARIES}) +IF(CURL_FOUND) + add_definitions(-DHAVE_LIBCURL) + target_link_libraries(hscript ${CURL_LIBRARIES}) +ENDIF(CURL_FOUND) + install(TARGETS hscript DESTINATION lib) install(FILES ${HSCRIPT_INCLUDE} DESTINATION include/hscript) diff --git a/hscript/meta.cc b/hscript/meta.cc index d664992..1124988 100644 --- a/hscript/meta.cc +++ b/hscript/meta.cc @@ -20,6 +20,7 @@ #endif /* HAS_INSTALL_ENV */ #include /* access - used by tz code even in RT env */ #include "meta.hh" +#include "util.hh" #include "util/output.hh" using namespace Horizon::Keys; @@ -511,6 +512,48 @@ bool SigningKey::validate(ScriptOptions) const { return true; } -bool SigningKey::execute(ScriptOptions) const { - return false; +bool SigningKey::execute(ScriptOptions opts) const { + /* everything after the last / in the value is the filename */ + const std::string name(_value.substr(_value.find_last_of('/') + 1)); + + const std::string target("/target/etc/apk/keys/" + name); + + output_info("installfile:" + std::to_string(line), + "signingkey: trusting " + name + " for repository signing"); + + if(opts.test(Simulate)) { + std::cout << "mkdir -p /target/etc/apk/keys" << std::endl; + if(_value[0] == '/') { + std::cout << "cp " << _value << " " << target << std::endl; + } else { + std::cout << "curl -L -o " << target << " " << _value << std::endl; + } + return true; + } + +#ifdef HAS_INSTALL_ENV + error_code ec; + if(!fs::exists("/target/etc/apk/keys")) { + fs::create_directory("/target/etc/apk/keys", ec); + if(ec) { + output_error("installfile:" + std::to_string(line), + "signingkey: could not initialise target repository " + "keys directory", ec.message()); + return false; + } + } + + if(_value[0] == '/') { + fs::copy_file(_value, target, fs_overwrite, ec); + if(ec) { + output_error("installfile:" + std::to_string(line), + "signingkey: could not copy signing key to target", + ec.message()); + return false; + } + } else { + return download_file(_value, target); + } +#endif /* HAS_INSTALL_ENV */ + return true; } diff --git a/hscript/script.cc b/hscript/script.cc index 6eebae8..4ed52b7 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -712,6 +712,26 @@ bool add_default_repos(std::vector> &repos) { } +/*! Add the default repository keys to the signing key list. + * @param keys The list of repository keys. + * The list +keys+ will be modified with the default repository signing keys + * for Adélie Linux. + */ +bool add_default_repo_keys(std::vector> &keys) { + Keys::SigningKey *key = dynamic_cast( + Horizon::Keys::SigningKey::parseFromData( + "/etc/apk/keys/packages@adelielinux.org.pub", 0, nullptr, nullptr) + ); + if(!key) { + output_error("internal", "failed to create default repository signing key"); + return false; + } + std::unique_ptr repo_key(key); + keys.push_back(std::move(repo_key)); + return true; +} + + bool Script::validate() const { int failures = 0; std::set seen_diskids, seen_labels, seen_parts, seen_pvs, @@ -822,6 +842,13 @@ bool Script::validate() const { "You may only specify up to 10 repositories."); } + /* REQ: Script.signingkey */ + if(this->internal->repo_keys.size() == 0) { + if(!add_default_repo_keys(this->internal->repo_keys)) { + return false; + } + } + /* REQ: Runner.Validate.signingkey */ for(auto &key : this->internal->repo_keys) { if(!key->validate(this->opts)) { diff --git a/hscript/util.cc b/hscript/util.cc new file mode 100644 index 0000000..4a991c5 --- /dev/null +++ b/hscript/util.cc @@ -0,0 +1,61 @@ +/* + * util.cc - Implementation of useful utility routines + * libhscript, the HorizonScript library for + * Project Horizon + * + * Copyright (c) 2019 Adélie Linux and contributors. All rights reserved. + * This code is licensed under the AGPL 3.0 license, as noted in the + * LICENSE-code file in the root directory of this repository. + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#include +#ifdef HAVE_LIBCURL +# include /* fopen */ +# include /* strerror */ +# include /* curl_* */ +# include /* errno */ +#endif /* HAVE_LIBCURL */ +#include "util/output.hh" + +#ifdef HAVE_LIBCURL +bool download_file(const std::string &url, const std::string &path) { + CURL *curl = curl_easy_init(); + CURLcode result; + bool return_code = false; + char errbuf[CURL_ERROR_SIZE]; + FILE *fp; + + if(curl == nullptr) { + output_error("internal", "trouble initialising cURL library"); + return false; + } + + fp = fopen(path.c_str(), "w"); + if(fp == nullptr) { + output_error("internal", "couldn't open " + path + " for writing", + strerror(errno)); + curl_easy_cleanup(curl); + return false; + } + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + + result = curl_easy_perform(curl); + if(result == CURLE_OK) { + return_code = true; + } else { + output_error("curl", "couldn't download file", errbuf); + } + curl_easy_cleanup(curl); + return return_code; +} +#else /* !HAVE_LIBCURL */ +bool download_file(const std::string &url, const std::string &path) { + output_error("internal", "can't download without linking to cURL"); + return false; +} +#endif /* HAVE_LIBCURL */ diff --git a/hscript/util.hh b/hscript/util.hh new file mode 100644 index 0000000..d350cd3 --- /dev/null +++ b/hscript/util.hh @@ -0,0 +1,25 @@ +/* + * util.cc - Definition of useful utility routines + * libhscript, the HorizonScript library for + * Project Horizon + * + * Copyright (c) 2019 Adélie Linux and contributors. All rights reserved. + * This code is licensed under the AGPL 3.0 license, as noted in the + * LICENSE-code file in the root directory of this repository. + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#ifndef HSCRIPT_UTIL_HH +#define HSCRIPT_UTIL_HH + +#include + +/*! Download the contents of a URL to a path. + * @param url The URL to download. + * @param path The path in which to save the file. + * @returns true if successful download, false otherwise. + */ +bool download_file(const std::string &url, const std::string &path); + +#endif /* !HSCRIPT_UTIL_HH */ -- cgit v1.2.3-60-g2f50