Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,25 @@ message(STATUS "Setting SOTA_CLIENT to ${SOTA_CLIENT}")
add_definitions('-g')
add_definitions('-Wall')

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake-modules)

# find all required libraries
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS filesystem iostreams program_options system REQUIRED)
find_package(CURL REQUIRED)
find_package(PkgConfig REQUIRED)
find_package(OpenSSL 3.0.0 REQUIRED)
pkg_search_module(GLIB REQUIRED glib-2.0)

# Use C++11, but without GNU or other extensions
set(CMAKE_CXX_STANDARD 11)

add_executable(lmp-device-register src/main.cpp)
target_include_directories(lmp-device-register PRIVATE ${GLIB_INCLUDE_DIRS})
target_link_libraries(lmp-device-register ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${GLIB_LDFLAGS})
if(DISABLE_PKCS11)
add_executable(lmp-device-register src/main.cpp src/options.cpp src/auth.cpp src/pkcs11_stub.cpp src/openssl.cpp)
target_link_libraries(lmp-device-register ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${GLIB_LDFLAGS} ${OPENSSL_LIBRARIES})
else(DISABLE_PKCS11)
pkg_check_modules(LIBP11 REQUIRED libp11)
add_executable(lmp-device-register src/main.cpp src/options.cpp src/auth.cpp src/pkcs11.cpp src/openssl.cpp)
target_link_libraries(lmp-device-register ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${GLIB_LDFLAGS} ${OPENSSL_LIBRARIES} ${LIBP11_LIBRARIES})
endif(DISABLE_PKCS11)

target_include_directories(lmp-device-register PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> ${GLIB_INCLUDE_DIRS})
install(TARGETS lmp-device-register RUNTIME DESTINATION bin)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use the libp11.pc pkgconfig provide in the project. With this we can remove the cmake-modules/FindLibP11.cmake

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,17 +46,15 @@ message(STATUS "Setting SOTA_CLIENT to ${SOTA_CLIENT}")
 add_definitions('-g')
 add_definitions('-Wall')
 
-set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake-modules)
-include_directories(SYSTEM ${LIBP11_INCLUDE_DIR})
-
 # find all required libraries
 set(Boost_USE_STATIC_LIBS ON)
 find_package(Boost COMPONENTS filesystem iostreams program_options system REQUIRED)
 find_package(CURL REQUIRED)
+find_package(OpenSSL 3.0.0 REQUIRED)
+
 find_package(PkgConfig REQUIRED)
-find_package(LibP11 REQUIRED)
-find_package(OpenSSL REQUIRED)
 pkg_search_module(GLIB REQUIRED glib-2.0)
+pkg_check_modules(LIBP11 REQUIRED libp11)
 
 # Use C++11, but without GNU or other extensions
 set(CMAKE_CXX_STANDARD 11)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would be great. let me test this.

133 changes: 133 additions & 0 deletions inc/curl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright (c) 2023 Foundries.io
*
* SPDX-License-Identifier: MIT
*/

#ifndef CURL_H
#define CURL_H

#include <boost/algorithm/string.hpp>
#include <boost/beast/core/detail/base64.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/interprocess/sync/file_lock.hpp>

#include <curl/curl.h>

using boost::property_tree::ptree;
using std::stringstream;
using std::string;
using std::cerr;
using std::cout;
using std::endl;

static size_t write_sstream(void *buf, size_t size, size_t nmemb, void *userp)
{
auto *body = static_cast<stringstream *>(userp);

body->write(static_cast<const char *>(buf), size * nmemb);

return size * nmemb;
}

class Curl {
private:
string _url;
public:
Curl(const string &url)
{
_url = url;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl != nullptr) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
}
}
~Curl()
{
if (curl != nullptr) {
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
void ParseResponse(stringstream &body, ptree &resp)
{
try {
read_json(body, resp);
} catch (const boost::property_tree::json_parser::json_parser_error &e) {
cerr << "Unable to parse response from: " << _url << " Error is:" << endl;
cerr << " " << e.message() << endl;
body.seekg(0);
cerr << "Raw response was: " << body.str() << endl;
}
}
std::tuple<bool, string> PingEndpoint()
{
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
return { false,
"Unable to reach the device registration endpoint " + _url + "; err: " + curl_easy_strerror(res) };
}
gint64 code = 0;
CURLcode get_info_res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (get_info_res != CURLE_OK) {
return { false,
"Error while checking the device registration endpoint; err: unable to get curl info: " + string(curl_easy_strerror(get_info_res)) };
}
if (code >= 500) {
// 401 or 400 is returned under normal circumstances what indicates that the OTA backend is reachable and functional
return { false,
"The device registration endpoint is not healthy" + _url + "; status code: " + std::to_string(code) };
}
return { true, "" };
}
gint64 Post(const http_headers &headers, const string &data, ptree &resp)
{
stringstream body;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_sstream);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());

struct curl_slist *chunk = nullptr;
for (auto item : headers) {
string header = item.first + ": " + item.second;
chunk = curl_slist_append(chunk, header.c_str());
}

if (chunk != nullptr) {
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
}

CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
cerr << "Unable to post to " << _url << ": " << curl_easy_strerror(res) << endl;
exit(1);
}

if (chunk != nullptr) {
curl_slist_free_all(chunk);
}

gint64 code = 0;
res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (res != CURLE_OK) {
cerr << "Unable to get curl info: " << curl_easy_strerror(res) << endl;
exit(1);
}
ParseResponse(body, resp);
return code;
}
private:
CURL *curl = nullptr;
};

#endif
115 changes: 115 additions & 0 deletions inc/device_register.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2023 Foundries.io
*
* SPDX-License-Identifier: MIT
*/

#ifndef DEVICE_REGISTER_H
#define DEVICE_REGISTER_H

#include <exception>
#include <fcntl.h>
#include <glib.h>
#include <iostream>
#include <regex>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string>
#include <sstream>
#include <unistd.h>

#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/encoder.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/buffer.h>

#include <boost/algorithm/string.hpp>
#include <boost/beast/core/detail/base64.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/program_options.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/interprocess/sync/file_lock.hpp>

#define __weak __attribute__((weak))

/* OS definitions in os-release */
#define LMP_OS_STR "/etc/os-release"
#define OS_FACTORY_TAG "LMP_FACTORY_TAG"
#define OS_FACTORY "LMP_FACTORY"

/* Environment Variables */
#define ENV_DEVICE_FACTORY "DEVICE_FACTORY"
#define ENV_PRODUCTION "PRODUCTION"
#define ENV_OAUTH_BASE "OAUTH_BASE"
#define ENV_DEVICE_API "DEVICE_API"

/* HSM defitions */
#define HSM_TOKEN_STR "aktualizr"
#define HSM_TLS_STR "tls"
#define HSM_TLS_ID_STR "01"
#define HSM_CRT_STR "client"
#define HSM_CRT_ID 3
#define HSM_CRT_ID_STR "03"

/* Files */
#define AKLITE_LOCK "/var/lock/aklite.lock"
#define SOTA_DIR "/var/sota"
#define SOTA_PEM "/client.pem"
#define SOTA_SQL "/sql.db"

using boost::property_tree::ptree;
using std::stringstream;
using std::string;
using std::cerr;
using std::cout;
using std::endl;

struct lmp_options {
string api_token_header;
string device_group;
string api_token;
string factory;
string hwid;
string uuid;
string name;
string hsm_module;
string hsm_so_pin;
string hsm_pin;
string sota_dir;
string pacman_tags;
bool start_daemon;
bool use_server;
bool production;
bool mlock;
#if defined DOCKER_COMPOSE_APP
string apps;
string restorable_apps;
#endif
};

typedef std::map<std::string, string> http_headers;

int auth_register_device(http_headers &headers, ptree &device, ptree &resp);
void auth_get_http_headers(lmp_options &opt, http_headers &headers);
int auth_ping_server(void);

int options_parse(int argc, char **argv, lmp_options &options);

int openssl_create_csr(const lmp_options &options, string &key, string &csr);
int openssl_gen_csr(const lmp_options &options, EVP_PKEY *pub, EVP_PKEY *priv,
string &csr);

int pkcs11_create_csr(const lmp_options &options, string &key, string &csr);
int pkcs11_store_cert(lmp_options &opt, X509 *cert);
int pkcs11_get_uuid(lmp_options &options);
#endif
Loading