1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/examples/XAdES/client.cpp
stefanocasazza d32d21a917 sync
2018-08-21 15:58:45 +02:00

442 lines
19 KiB
C++

// client.cpp
#include <ulib/file_config.h>
#include <ulib/net/tcpsocket.h>
#include <ulib/xml/soap/soap_client.h>
#undef PACKAGE
#define PACKAGE "client"
#undef ARGS
#define ARGS "type_of_signature <parameters>"
#define PURPOSE \
"client interface to server SOAP managing XAdES\n" \
"----------------------------------------------------------------------------------------------------------------------------------\n" \
"List of XAdES signatures:\n" \
"\n" \
" 1 - BES - parameters: <URI> <X509> <key> [digest] [SigningTime] [ClaimedRole] [ProductionPlace...] \n" \
" 2 - C - parameters: <URI> <X509> <key> [digest] [SigningTime] [ClaimedRole] [ProductionPlace...] [CAStore] [SignatureTimeStamp]\n" \
" 3 - L - parameters: <XAdES-C> [ArchiveTimeStamp] [Schema]\n" \
"----------------------------------------------------------------------------------------------------------------------------------"
#define U_OPTIONS \
"option c config 1 'path of configuration file' ''\n"
#include <ulib/application.h>
#define U_DATA_URI (const char*)(lnum_args >= 1 ? argv[optind+0] : "")
#define U_X509 (const char*)(lnum_args >= 2 ? argv[optind+1] : "")
#define U_KEY_HANDLE (const char*)(lnum_args >= 3 ? argv[optind+2] : "")
#define U_DIGEST_ALGORITHM (const char*)(lnum_args >= 4 ? argv[optind+3] : "")
#define U_SIGNING_TIME (lnum_args >= 5 ? u_atoi(argv[optind+4]) : 0)
#define U_CLAIMED_ROLE (const char*)(lnum_args >= 6 ? argv[optind+5] : "")
#define U_PRODUCTION_PLACE_CITY (const char*)(lnum_args >= 7 ? argv[optind+6] : "")
#define U_PRODUCTION_PLACE_STATE_OR_PROVINCE (const char*)(lnum_args >= 8 ? argv[optind+7] : "")
#define U_PRODUCTION_PLACE_POSTAL_CODE (const char*)(lnum_args >= 9 ? argv[optind+8] : "")
#define U_PRODUCTION_PLACE_COUNTRY_NAME (const char*)(lnum_args >= 10 ? argv[optind+9] : "")
#define U_CA_STORE (const char*)(lnum_args >= 11 ? argv[optind+10] : "")
#define U_SIGNATURE_TIMESTAMP (const char*)(lnum_args >= 12 ? argv[optind+11] : "")
#define U_ARCHIVE_TIMESTAMP (const char*)(lnum_args >= 0 ? argv[optind+0] : "")
#define U_SCHEMA (const char*)(lnum_args >= 1 ? argv[optind+1] : "")
template <class T> class UClientXAdES : public USOAPClient<T> {
public:
// COSTRUTTORE
explicit UClientXAdES(UFileConfig* cfg) : USOAPClient<T>(cfg) {}
virtual ~UClientXAdES() {}
// OBJECT FOR METHOD REQUEST
class XAdES_BES : public URPCMethod { // URPCMethod provides an interface for the things that methods most know how to do
public:
// ---------------------------------------------------------------------------------------------------------------
// Firma dati: XAdES-BES
// ---------------------------------------------------------------------------------------------------------------
// DATA = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" stdin (base64 encoded)
// DATA_URI = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input
// X509 = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (formato PEM)
// KEY_HANDLE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input
// DIGEST_ALGORITHM = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// SIGNING_TIME = boolean "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// CLAIMED_ROLE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_CITY = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_STATE_OR_PROVINCE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_POSTAL_CODE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_COUNTRY_NAME = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// ---------------------------------------------------------------------------------------------------------------
// result = xml signed (base64 encoded)
// ---------------------------------------------------------------------------------------------------------------
uint32_t SIGNING_TIME;
UString DATA, DATA_URI, X509, KEY_HANDLE, DIGEST_ALGORITHM, CLAIMED_ROLE, PRODUCTION_PLACE_CITY,
PRODUCTION_PLACE_STATE_OR_PROVINCE, PRODUCTION_PLACE_POSTAL_CODE, PRODUCTION_PLACE_COUNTRY_NAME;
XAdES_BES()
{
U_TRACE_CTOR(5, XAdES_BES, "")
SIGNING_TIME = 0;
URPCMethod::method_name = U_STRING_FROM_CONSTANT("XAdES-BES");
}
virtual ~XAdES_BES()
{
U_TRACE_DTOR(5, XAdES_BES)
}
// Transforms the method into something that SOAP servers and client can send.
// The encoder holds the actual data while the client hands data to be entered in
virtual void encode()
{
U_TRACE(5, "XAdES_BES::encode()")
U_SOAP_ENCB64_ARG(DATA);
U_SOAP_ENCODE_ARG(DATA_URI);
U_SOAP_ENCODE_ARG(X509);
U_SOAP_ENCODE_ARG(KEY_HANDLE);
U_SOAP_ENCODE_ARG(DIGEST_ALGORITHM);
U_SOAP_ENCODE_ARG(SIGNING_TIME);
U_SOAP_ENCODE_ARG(CLAIMED_ROLE);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_CITY);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_STATE_OR_PROVINCE);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_POSTAL_CODE);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_COUNTRY_NAME);
}
};
class XAdES_C : public URPCMethod { // URPCMethod provides an interface for the things that methods most know how to do
public:
// ---------------------------------------------------------------------------------------------------------------
// Firma dati: XAdES-C
// ---------------------------------------------------------------------------------------------------------------
// DATA = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" stdin (base64 encoded)
// DATA_URI = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input
// X509 = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (formato PEM)
// KEY_HANDLE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input
// DIGEST_ALGORITHM = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// SIGNING_TIME = boolean "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// CLAIMED_ROLE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_CITY = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_STATE_OR_PROVINCE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_POSTAL_CODE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// PRODUCTION_PLACE_COUNTRY_NAME = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// CA_STORE = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// SIGNATURE_TIMESTAMP = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// ---------------------------------------------------------------------------------------------------------------
// result = xml signed (base64 encoded)
// ---------------------------------------------------------------------------------------------------------------
uint32_t SIGNING_TIME;
UString DATA, DATA_URI, X509, KEY_HANDLE, DIGEST_ALGORITHM, CLAIMED_ROLE, PRODUCTION_PLACE_CITY,
PRODUCTION_PLACE_STATE_OR_PROVINCE, PRODUCTION_PLACE_POSTAL_CODE, PRODUCTION_PLACE_COUNTRY_NAME,
CA_STORE, SIGNATURE_TIMESTAMP;
XAdES_C()
{
U_TRACE_CTOR(5, XAdES_C, "")
SIGNING_TIME = 0;
URPCMethod::method_name = U_STRING_FROM_CONSTANT("XAdES-C");
}
virtual ~XAdES_C()
{
U_TRACE_DTOR(5, XAdES_C)
}
// Transforms the method into something that SOAP servers and client can send.
// The encoder holds the actual data while the client hands data to be entered in
virtual void encode()
{
U_TRACE(5, "XAdES_C::encode()")
U_SOAP_ENCB64_ARG(DATA);
U_SOAP_ENCODE_ARG(DATA_URI);
U_SOAP_ENCODE_ARG(X509);
U_SOAP_ENCODE_ARG(KEY_HANDLE);
U_SOAP_ENCODE_ARG(DIGEST_ALGORITHM);
U_SOAP_ENCODE_ARG(SIGNING_TIME);
U_SOAP_ENCODE_ARG(CLAIMED_ROLE);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_CITY);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_STATE_OR_PROVINCE);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_POSTAL_CODE);
U_SOAP_ENCODE_ARG(PRODUCTION_PLACE_COUNTRY_NAME);
U_SOAP_ENCODE_ARG(CA_STORE);
U_SOAP_ENCODE_ARG(SIGNATURE_TIMESTAMP);
}
};
class XAdES_L : public URPCMethod { // URPCMethod provides an interface for the things that methods most know how to do
public:
// ---------------------------------------------------------------------------------------------------------------
// Firma dati: XAdES-L
// ---------------------------------------------------------------------------------------------------------------
// XAdES-C = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" stdin (base64 encoded)
// ARCHIVE_TIMESTAMP = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// SCHEMA = stringa "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" input (op)
// ---------------------------------------------------------------------------------------------------------------
// result = xml signed (base64 encoded)
// ---------------------------------------------------------------------------------------------------------------
UString DATA, ARCHIVE_TIMESTAMP, SCHEMA;
XAdES_L()
{
U_TRACE_CTOR(5, XAdES_L, "")
URPCMethod::method_name = U_STRING_FROM_CONSTANT("XAdES-L");
}
virtual ~XAdES_L()
{
U_TRACE_DTOR(5, XAdES_L)
}
// Transforms the method into something that SOAP servers and client can send.
// The encoder holds the actual data while the client hands data to be entered in
virtual void encode()
{
U_TRACE(5, "XAdES_L::encode()")
U_SOAP_ENCB64_ARG(DATA);
U_SOAP_ENCODE_ARG(ARCHIVE_TIMESTAMP);
U_SOAP_ENCODE_ARG(SCHEMA);
}
};
XAdES_BES m_XAdES_BES;
XAdES_C m_XAdES_C;
XAdES_L m_XAdES_L;
// SERVICES
UString creatBES(const UString& data, const char* data_uri, const UString& x509, const char* key_handle,
const char* digest_algorithm, uint32_t signing_time, const char* claimed_role,
const char* production_place_city, const char* production_place_state_or_province,
const char* production_place_postal_code, const char* production_place_country_name) // 1
{
U_TRACE(5, "UClientXAdES::creatBES(%.*S,%S,%.*S,%S,%S,%u,%S,%S,%S,%S,%S)", U_STRING_TO_TRACE(data), data_uri, U_STRING_TO_TRACE(x509),
key_handle, digest_algorithm, signing_time, claimed_role, production_place_city,
production_place_state_or_province, production_place_postal_code, production_place_country_name)
m_XAdES_BES.DATA = data;
m_XAdES_BES.DATA_URI = data_uri;
m_XAdES_BES.X509 = x509;
m_XAdES_BES.KEY_HANDLE = key_handle;
m_XAdES_BES.DIGEST_ALGORITHM = digest_algorithm;
m_XAdES_BES.SIGNING_TIME = signing_time;
m_XAdES_BES.CLAIMED_ROLE = claimed_role;
m_XAdES_BES.PRODUCTION_PLACE_CITY = production_place_city;
m_XAdES_BES.PRODUCTION_PLACE_STATE_OR_PROVINCE = production_place_state_or_province;
m_XAdES_BES.PRODUCTION_PLACE_POSTAL_CODE = production_place_postal_code;
m_XAdES_BES.PRODUCTION_PLACE_COUNTRY_NAME = production_place_country_name;
if (USOAPClient<T>::processRequest(m_XAdES_BES))
{
UString result = USOAPClient<T>::getResponse(); // Get the value of the element inside the response
UString _buffer(result.size());
UBase64::decode(result, _buffer);
if (_buffer) U_RETURN_STRING(_buffer);
}
return UString::getStringNull();
}
UString creatC(const UString& data, const char* data_uri, const UString& x509, const char* key_handle,
const char* digest_algorithm, uint32_t signing_time, const char* claimed_role,
const char* production_place_city, const char* production_place_state_or_province,
const char* production_place_postal_code, const char* production_place_country_name,
const char* ca_store, const char* signature_timestamp) // 2
{
U_TRACE(5, "UClientXAdES::creatC(%.*S,%S)", U_STRING_TO_TRACE(data), data_uri)
m_XAdES_C.DATA = data;
m_XAdES_C.DATA_URI = data_uri;
m_XAdES_C.X509 = x509;
m_XAdES_C.KEY_HANDLE = key_handle;
m_XAdES_C.DIGEST_ALGORITHM = digest_algorithm;
m_XAdES_C.SIGNING_TIME = signing_time;
m_XAdES_C.CLAIMED_ROLE = claimed_role;
m_XAdES_C.PRODUCTION_PLACE_CITY = production_place_city;
m_XAdES_C.PRODUCTION_PLACE_STATE_OR_PROVINCE = production_place_state_or_province;
m_XAdES_C.PRODUCTION_PLACE_POSTAL_CODE = production_place_postal_code;
m_XAdES_C.PRODUCTION_PLACE_COUNTRY_NAME = production_place_country_name;
m_XAdES_C.CA_STORE = ca_store;
m_XAdES_C.SIGNATURE_TIMESTAMP = signature_timestamp;
if (USOAPClient<T>::processRequest(m_XAdES_C))
{
UString result = USOAPClient<T>::getResponse(); // Get the value of the element inside the response
UString _buffer(result.size());
UBase64::decode(result, _buffer);
if (_buffer) U_RETURN_STRING(_buffer);
}
return UString::getStringNull();
}
UString creatL(const UString& data, const char* archive_timestamp, const char* schema) // 2
{
U_TRACE(5, "UClientXAdES::creatL(%.*S,%S,%S)", U_STRING_TO_TRACE(data), archive_timestamp, schema)
m_XAdES_L.DATA = data;
m_XAdES_L.ARCHIVE_TIMESTAMP = archive_timestamp;
m_XAdES_L.SCHEMA = schema;
if (USOAPClient<T>::processRequest(m_XAdES_L))
{
UString result = USOAPClient<T>::getResponse(); // Get the value of the element inside the response
UString _buffer(result.size());
UBase64::decode(result, _buffer);
if (_buffer) U_RETURN_STRING(_buffer);
}
return UString::getStringNull();
}
};
class Application : public UApplication {
public:
Application()
{
U_TRACE(5, "Application::Application()")
client = U_NULLPTR;
}
~Application()
{
U_TRACE(5, "Application::~Application()")
U_DELETE(client)
}
void run(int argc, char* argv[], char* env[])
{
U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env)
UApplication::run(argc, argv, env);
// manage options
UString cfg_str;
UFileConfig cfg;
if (UApplication::isOptions()) cfg_str = opt['c'];
// manage arg operation
const char* method = argv[optind++];
if (method == U_NULLPTR) usage();
int op = u_atoi(method), lnum_args = (argc - optind);
U_INTERNAL_DUMP("optind = %d lnum_args = %d", optind, lnum_args)
// manage file configuration
if (cfg_str.empty()) cfg_str = U_STRING_FROM_CONSTANT("XAdESclient.cfg");
cfg.UFile::setPath(cfg_str);
// -----------------------------------------------------------------------------------------------
// client XAdES - configuration parameters
// -----------------------------------------------------------------------------------------------
// ENABLE_IPV6 flag to indicate use of ipv6
// SERVER host name or ip address for server
// PORT port number for the server
// -----------------------------------------------------------------------------------------------
client = new UClientXAdES<UTCPSocket>(&cfg);
UString result;
UApplication::exit_value = 1;
if (client->connect())
{
switch (op)
{
case 1: // Firma dati: XAdES-BES
{
UString x = UFile::contentOf(UString(U_X509)),
data = UFile::contentOf(UString(U_DATA_URI));
result = client->creatBES(data, U_DATA_URI, x, U_KEY_HANDLE, U_DIGEST_ALGORITHM,
U_SIGNING_TIME, U_CLAIMED_ROLE, U_PRODUCTION_PLACE_CITY,
U_PRODUCTION_PLACE_STATE_OR_PROVINCE, U_PRODUCTION_PLACE_POSTAL_CODE,
U_PRODUCTION_PLACE_COUNTRY_NAME);
}
break;
case 2: // Firma dati: XAdES-C
{
UString x = UFile::contentOf(UString(U_X509)),
data = UFile::contentOf(UString(U_DATA_URI));
result = client->creatC(data, U_DATA_URI, x, U_KEY_HANDLE, U_DIGEST_ALGORITHM,
U_SIGNING_TIME, U_CLAIMED_ROLE, U_PRODUCTION_PLACE_CITY,
U_PRODUCTION_PLACE_STATE_OR_PROVINCE, U_PRODUCTION_PLACE_POSTAL_CODE,
U_PRODUCTION_PLACE_COUNTRY_NAME,
U_CA_STORE, U_SIGNATURE_TIMESTAMP);
}
break;
case 3: // Archiviazione XAdES-C: XAdES-L
{
UString data = UFile::contentOf(UString(U_DATA_URI));
result = client->creatL(data, U_ARCHIVE_TIMESTAMP, U_SCHEMA);
}
break;
default:
U_ERROR("type_of_signature not valid");
break;
}
if (result)
{
std::cout.write(result.data(), result.size());
UApplication::exit_value = 0;
}
if (UApplication::exit_value == 1)
{
result = client->getResponse();
if (result) U_WARNING("%v", result.rep);
}
}
client->closeLog();
}
private:
UClientXAdES<UTCPSocket>* client;
};
U_MAIN