Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+33
View File
@@ -0,0 +1,33 @@
#
# Generates certificates from a json list of workstations and
# generates an sql file from it
#
# $Id: CMakeLists.txt 47272 2019-06-21 05:31:48Z wille_m $
# $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Tools/Splash/CMakeLists.txt $
# $Author: wille_m $
#
# Created by Mike Wille, SLTE, 2020-10-10
#
if(NOT WIN32)
if(BOTAN_FOUND AND CMAKE_VERSION VERSION_GREATER 3.15.9) # don't build AsmWorkstationCertifier if cmake < 3.16
set(src_AsmWorkstationCertifier
main.cpp
)
NGL_ADD_EXECUTABLE(SV AsmWorkstationCertifier ${src_AsmWorkstationCertifier})
NGL_TARGET_LINK_LIBRARIES(AsmWorkstationCertifier
Qt5::Core
LtsBotan
nglcoreapplication
NGLLogger
)
NGL_INSTALL_TARGET(AsmWorkstationCertifier)
else()
message(WARNING "No botan2, no AsmWorkstationCertifier")
endif()
else(NOT WIN32)
message(WARNING "No Unix, no botan2, no AsmWorkstationCertifier")
endif(NOT WIN32)
+16
View File
@@ -0,0 +1,16 @@
License for fast-ca code parts:
MIT License
Copyright (c) 2020 Mike Wille <mike@wille.io>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+264
View File
@@ -0,0 +1,264 @@
/**
* @RDE_HEADER@
* Generates an SQL file from a workstation JSON file (usually located under Lts/Tests/DatabaseInitialisation/%project%_asm_values_workstations.json)
* $Id: tpm_exported_scripts_dialog.cpp 52234 2020-10-01 13:34:21Z wille_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_dialog.cpp $
* $Author: wille_m $
*
* Created by Mike Wille, SLTE, 2020-10-10
*/
// Parts stolen from https://github.com/wille-io/fast-ca/blob/master/main.cpp @ https://github.com/wille-io/fast-ca/blob/7cd703a2751d995da5b0f918198532d4955934f6/main.cpp
#include <botan/x509_ca.h>
#include <botan/x509cert.h>
#include <botan/x509self.h>
#include <botan/rsa.h>
#include <botan/pk_keys.h>
#include <botan/bigint.h>
#include <botan/auto_rng.h>
#include <botan/pubkey.h> // bug: botan 2.12.1 does a sizeof for (undefined) PK_Signer when using X509CA
#include <botan/pkcs8.h>
#include <stdio.h>
#include <string>
#include <memory>
#include <vector>
#include <unistd.h> // grr.. not portable
#include <termios.h> // blank pwd / echo on/off
#include <iostream>
#include <nglapplication/nglcoreapplication.h>
#include <NGLLogger/INGLLogger.h>
#include <QFile>
#include <QSaveFile>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
#include <QJsonArray>
#include <QTextStream>
using namespace Botan;
termios t;
void echoRestore()
{
tcsetattr(STDIN_FILENO, TCSANOW, &t);
}
void echoOff()
{
termios _t;
tcgetattr(STDIN_FILENO, &_t);
t = _t;
_t.c_lflag &= ~ECHO;
tcsetattr(STDIN_FILENO, TCSAFLUSH, &_t);
}
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
app.createLogger("AsmWorkstationCertifier");
NGL::INGLLogger &logger(app.baseLogger());
STARTUP_LOG(logger);
QStringList args(app.arguments());
if (args.count() < 5)
{
ERROR_LOG(logger) << "usage: <input (project_asm_values_worksations.json)>"
<< " <output (project_asm_values_workstations.sql)>"
<< " <ca certificate (ca.crt)>"
<< " <ca private key (ca.ber)>";
return -1;
}
QString inputFile(args.at(1));
QString outputFile(args.at(2));
DEBUG_LOG(logger) << "input file: " << inputFile << ", output file: " << outputFile;
QFile input(inputFile);
if (!input.open(QIODevice::ReadOnly | QIODevice::Text))
{
ERROR_LOG(logger) << "cannot open input file: " << input.errorString();
return -1;
}
// botan stuff
INFO_LOG(logger) << "Loading CA certificate ...";
X509_Certificate caCert = X509_Certificate(args.at(3).toStdString());
AutoSeeded_RNG rng;
INFO_LOG(logger) << "Loading CA key ...";
Private_Key *caPrivKey = nullptr;
std::string pwd;
printf("> Enter the CA's private key's password: ");
echoOff();
std::cin >> pwd;
echoRestore();
printf("\n");
try
{
caPrivKey = PKCS8::load_key(args.at(4).toStdString(), rng, pwd);
}
catch(...)
{
ERROR_LOG(logger) << "CA keys couldn't be unlocked with the given password!";
return -1;
}
INFO_LOG(logger) << "Initializing CA ...";
X509_CA ca = X509_CA(caCert, *caPrivKey, "SHA-256", rng);
// TODO: free caPrivKey
QSaveFile output(outputFile);
if (!output.open(QIODevice::WriteOnly | QIODevice::Truncate /* empty file */ | QIODevice::Text))
{
ERROR_LOG(logger) << "cannot open / create output file: " << output.errorString();
return -1;
}
QTextStream os(&output);
// INSERT INTO asm.asm_asset(id, name, asset_type_id, location_id, certificate) VALUES
os << "-- Do not edit this file! File was generated with: " << args.join(QStringLiteral(" ")) << endl
<< endl
<< endl
<< "-- @RDE_HEADER@" << endl
<< "-- SQL file for asm.asm_asset with generated certificates per hostname" << endl
<< "-- $Id: $" << endl
<< "-- $HeadURL: $" << endl
<< "-- $Author: $" << endl
<< endl
<< "-- Created by Mike Wille, SLTE, 2020-10-10" << endl
<< endl
<< endl;
os << "-- Workstations";
QJsonParseError err;
QJsonDocument doc(QJsonDocument::fromJson(input.readAll(), &err));
if (err.error != QJsonParseError::NoError)
{
ERROR_LOG(logger) << "JSON input file " << inputFile << " contains an invalid json document: " << err.errorString() << " at offset " << err.offset;
return -1;
}
QJsonObject root(doc.object());
if (root.isEmpty())
{
ERROR_LOG(logger) << "JSON input file " << inputFile << " is missing the root object";
return -1;
}
QJsonArray grpArr(root[QStringLiteral("groups")].toArray());
if (grpArr.isEmpty())
{
ERROR_LOG(logger) << "JSON input file " << inputFile << " is missing the groups array";
return -1;
}
for (QJsonValueRef grpRef : grpArr)
{
const QJsonObject grp(grpRef.toObject());
os << endl << endl << "-- " << grp[QStringLiteral("name")].toString() << endl;
os << "INSERT INTO asm.asm_asset(id, name, asset_type_id, location_id, certificate) VALUES" << endl;
QJsonArray wsArr(grp[QStringLiteral("workstations")].toArray());
if (wsArr.isEmpty())
{
ERROR_LOG(logger) << "JSON input file " << inputFile << " is missing the workstations array in a group";
return -1;
}
bool first = true;
for (const QJsonValue &wsRef : qAsConst(wsArr))
{
const QJsonObject ws(wsRef.toObject());
int id = ws[QStringLiteral("id")].toInt();
QString host = ws[QStringLiteral("host")].toString();
int asset = ws[QStringLiteral("asset")].toInt();
int location = ws[QStringLiteral("location")].toInt();
if (first)
first = false;
else
os << endl << ",";
INFO_LOG(logger) << "Creating client keys for " << host << "...";
RSA_PrivateKey privKey = RSA_PrivateKey(rng, 4096);
std::string fqdn(host.toStdString());
INFO_LOG(logger) << "Creating client certificate request ...";
X509_Cert_Options opts("");
opts.common_name = fqdn;
opts.dns = fqdn;
opts.add_constraints(Key_Constraints::DIGITAL_SIGNATURE);
opts.add_ex_constraint("PKIX.ClientAuth");
PKCS10_Request request = X509::create_cert_req(opts, privKey, "SHA-256", rng);
INFO_LOG(logger) << "Creating client certificate ...";
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
X509_Certificate cert = ca.sign_request(request, rng, X509_Time(now),
X509_Time(now + std::chrono::hours(20 * 365 * 24))); // creates a certificate that is valid from now, for incredible 20 years (that should really be enough for a software in an age of super fast code depreciation)
std::string certData = cert.PEM_encode();
os << "( " << id << ", '" << host << "', " << asset << ", " << location << ", decode('"
<< QString::fromUtf8(QString::fromStdString(certData).toUtf8().toHex()) // wow
<< "', 'hex'))";
DEBUG_LOG(logger) << "Worksation '"<<ws[QStringLiteral("host")].toString()<<"' done!";
}
os << ";";
DEBUG_LOG(logger) << "Group '"<<grp[QStringLiteral("name")].toString()<<"' done!";
}
os << endl
<< endl
<< "ALTER SEQUENCE asm.asm_asset_id_seq RESTART WITH 200;";
os.flush();
if (!output.commit())
{
ERROR_LOG(logger) << "Unable to commit output file data! " << output.errorString();
return -1;
}
SHUTDOWN_LOG(logger);
return 0;
}