/
githubmirror
/
xmlsec
Обзор
Документация
Войти
/
githubmirror
/
xmlsec
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
1.3.9
apps/xmlsec.c
3 879 строк
131 KB
lsh123
(xmlsec-openssl) Add an option to dump OpenSSL errors on exit and disable tests with md5 certs for BoringSSL (#980)
01 ноя 2025, 07:11
Не верифицирован
01 ноя 2025, 07:11
a47e80c
Код
Авторство
О чём код?
/** * XML Security Library (http://www.aleksey.com/xmlsec). * * Command line utility. * * See Copyright for the status of this software. * * Copyright (C) 2002-2024 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. */ #include <stdlib.h> #include <string.h> #include <time.h> #if !defined(_MSC_VER) #include <libgen.h> #endif /* defined(_MSC_VER) */ #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif /* defined(_MSC_VER) && _MSC_VER < 1900 */ #include <libxml/tree.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> #include <libxml/xpath.h> #include <libxml/xmlsave.h> #include <libxml/xpathInternals.h> #ifndef XMLSEC_NO_XSLT #include <libxslt/xslt.h> #include <libxslt/extensions.h> #include <libxslt/xsltInternals.h> #include <libxslt/xsltutils.h> #include <libxslt/security.h> #include <libexslt/exslt.h> #endif /* XMLSEC_NO_XSLT */ #include <xmlsec/xmlsec.h> #include <xmlsec/xmltree.h> #include <xmlsec/base64.h> #include <xmlsec/keys.h> #include <xmlsec/keyinfo.h> #include <xmlsec/keysmngr.h> #include <xmlsec/io.h> #include <xmlsec/transforms.h> #include <xmlsec/xmldsig.h> #include <xmlsec/xmlenc.h> #include <xmlsec/parser.h> #include <xmlsec/templates.h> #include <xmlsec/errors.h> #include "crypto.h" #include "cmdline.h" #if defined(_MSC_VER) && defined(_DEBUG) #include <crtdbg.h> #endif /*defined(_MSC_VER) && defined(_DEBUG) */ static const char copyright[] = "Written by Aleksey Sanin <aleksey@aleksey.com>.\n\n" "Copyright (C) 2002-2024 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.\n" "This is free software: see the source for copying information.\n"; static const char bugs[] = "Report bugs to http://www.aleksey.com/xmlsec/bugs.html\n"; static const char helpCommands1[] = "Usage: xmlsec <command> [<options>] [<files>]\n" "\n" "xmlsec is a command line tool for signing, verifying, encrypting and\n" "decrypting XML documents. The allowed <command> values are:\n" " --help " "\tdisplay this help information and exit\n" " --help-all " "\tdisplay help information for all commands/options and exit\n" " --help-<cmd>" "\tdisplay help information for command <cmd> and exit\n" " --version " "\tprint version information and exit\n" " --keys " "\tkeys XML file manipulation\n"; static const char helpCommands2[] = #ifndef XMLSEC_NO_XMLDSIG " --sign " "\tsign data and output XML document\n" " --verify " "\tverify signed document\n" #ifndef XMLSEC_NO_TMPL_TEST " --sign-tmpl " "\tcreate and sign dynamicaly generated signature template\n" #endif /* XMLSEC_NO_TMPL_TEST */ #endif /* XMLSEC_NO_XMLDSIG */ #ifndef XMLSEC_NO_XMLENC " --encrypt " "\tencrypt data and output XML document\n" " --decrypt " "\tdecrypt data from XML document\n" #endif /* XMLSEC_NO_XMLENC */ ; static const char helpVersion[] = "Usage: xmlsec version\n" "Prints version information and exits\n"; static const char helpKeys[] = "Usage: xmlsec keys [<options>] <file>\n" "Creates a new XML keys file <file>\n"; static const char helpSign[] = "Usage: xmlsec sign [<options>] <file>\n" "Calculates XML Digital Signature using template file <file>\n"; static const char helpVerify[] = "Usage: xmlsec verify [<options>] <file>\n" "Verifies XML Digital Signature in the <file>\n"; static const char helpSignTmpl[] = "Usage: xmlsec sign-tmpl [<options>]\n" "Creates a simple dynamic template and calculates XML Digital Signature\n" "(for testing only).\n"; static const char helpEncrypt[] = "Usage: xmlsec encrypt [<options>] <file>\n" "Encrypts data and creates XML Encryption using template file <file>\n"; static const char helpEncryptTmpl[] = "Usage: xmlsec encrypt [<options>]\n" "Creates a simple dynamic template and calculates XML Encryption\n"; static const char helpDecrypt[] = "Usage: xmlsec decrypt [<options>] <file>\n" "Decrypts XML Encryption data in the <file>\n"; static const char helpListKeyData[] = "Usage: xmlsec list-key-data\n" "Prints the list of known key data klasses\n"; static const char helpCheckKeyData[] = "Usage: xmlsec check-key-data <key-data-name> [<key-data-name> ... ]\n" "Checks the given key-data against the list of known key-data klasses\n"; static const char helpListTransforms[] = "Usage: xmlsec list-transforms\n" "Prints the list of known transform klasses\n"; static const char helpCheckTransforms[] = "Usage: xmlsec check-transforms <transform-name> [<transform-name> ... ]\n" "Checks the given transforms against the list of known transform klasses\n"; #define xmlSecAppCmdLineTopicGeneral 0x0001 #define xmlSecAppCmdLineTopicDSigCommon 0x0002 #define xmlSecAppCmdLineTopicDSigSign 0x0004 #define xmlSecAppCmdLineTopicDSigVerify 0x0008 #define xmlSecAppCmdLineTopicEncCommon 0x0010 #define xmlSecAppCmdLineTopicEncEncrypt 0x0020 #define xmlSecAppCmdLineTopicEncDecrypt 0x0040 /* #define UNUSED 0x0080 */ #define xmlSecAppCmdLineTopicKeysMngr 0x1000 #define xmlSecAppCmdLineTopicX509Certs 0x2000 #define xmlSecAppCmdLineTopicVersion 0x4000 #define xmlSecAppCmdLineTopicCryptoConfig 0x8000 #define xmlSecAppCmdLineTopicAll 0xFFFF /**************************************************************** * * General configuration params * ***************************************************************/ static xmlSecAppCmdLineParam helpParam = { xmlSecAppCmdLineTopicGeneral, "--help", "-h", "--help" "\n\tprint help information about the command", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam cryptoParam = { xmlSecAppCmdLineTopicCryptoConfig, "--crypto", NULL, "--crypto <name>" "\n\tthe name of the crypto engine to use from the following" "\n\tlist: openssl, mscrypto, nss, gnutls, gcrypt (if no crypto engine is" "\n\tspecified then the default one is used)", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam cryptoConfigParam = { xmlSecAppCmdLineTopicCryptoConfig, "--crypto-config", NULL, "--crypto-config <path>" "\n\tpath to crypto engine configuration", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam repeatParam = { xmlSecAppCmdLineTopicCryptoConfig, "--repeat", "-r", "--repeat <number>" "\n\trepeat the operation <number> times", xmlSecAppCmdLineParamTypeNumber, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam base64LineSizeParam = { xmlSecAppCmdLineTopicCryptoConfig, "--base64-line-size", NULL, "--base64-line-size <size>" "\n\tsets the max line size for base64 encodings to <size>", xmlSecAppCmdLineParamTypeNumber, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam transformBinChunkSizeParam = { xmlSecAppCmdLineTopicCryptoConfig, "--transform-binary-chunk-size", NULL, "--transform-binary-chunk-size <size>" "\n\tsets the transforms binary processing chunk size to <size>; " "\n\tincreasing chunk size might improve performance at the expense" "\n\tof increased memory usage", xmlSecAppCmdLineParamTypeNumber, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam verboseParam = { xmlSecAppCmdLineTopicGeneral, "--verbose", NULL, "--verbose" "\n\tprint detailed error messages", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam printCryptoErrorsParam = { xmlSecAppCmdLineTopicGeneral, "--print-crypto-library-errors", NULL, "--print-crypto-library-errors" "\n\tprint errors from crypto library (OpenSSL only)", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; /**************************************************************** * * Keys Manager params * ***************************************************************/ static xmlSecAppCmdLineParam genKeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--gen-key", "-g", "--gen-key[:<name>] <keyKlass>-<keySize>" "\n\tgenerate new <keyKlass> key of <keySize> bits size," "\n\tset the key name to <name> and add the result to keys" "\n\tmanager (for example, \"--gen:mykey rsa-1024\" generates" "\n\ta new 1024 bits RSA key and sets it's name to \"mykey\")", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam keysFileParam = { xmlSecAppCmdLineTopicKeysMngr, "--keys-file", "-k", "--keys-file <file>" "\n\tload keys from XML file", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam privkeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--privkey-pem", "--privkey", "--privkey-pem[:<name>] <file>[,<cafile>[,<cafile>[...]]]" "\n\tload private key from PEM file and certificates" "\n\tthat verify this key", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam privkeyDerParam = { xmlSecAppCmdLineTopicKeysMngr, "--privkey-der", NULL, "--privkey-der[:<name>] <file>[,<cafile>[,<cafile>[...]]]" "\n\tload private key from DER file and certificates" "\n\tthat verify this key", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam pkcs8PemParam = { xmlSecAppCmdLineTopicKeysMngr, "--pkcs8-pem", "--privkey-p8-pem", "--pkcs8-pem[:<name>] <file>[,<cafile>[,<cafile>[...]]]" "\n\tload private key from PKCS8 PEM file and PEM certificates" "\n\tthat verify this key", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam pkcs8DerParam = { xmlSecAppCmdLineTopicKeysMngr, "--pkcs8-der", "--privkey-p8-der", "--pkcs8-der[:<name>] <file>[,<cafile>[,<cafile>[...]]]" "\n\tload private key from PKCS8 DER file and DER certificates" "\n\tthat verify this key", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; /* openssl specific privkey options */ static xmlSecAppCmdLineParam privkeyOpensslStoreParam = { xmlSecAppCmdLineTopicKeysMngr, "--privkey-openssl-store", NULL, "--privkey-openssl-store[:<name>] <uri>" "\n\tload private key and certs through OpenSSL ossl_store interface (e.g. from HSM)", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam privkeyOpensslEngineParam = { xmlSecAppCmdLineTopicKeysMngr, "--privkey-openssl-engine", NULL, "--privkey-openssl-engine[:<name>] <openssl-engine>;<openssl-key-id>[,<crtfile>[,<crtfile>[...]]]" "\n\tload private key by OpenSSL ENGINE interface; specify the name of engine" "\n\t(like with -engine params), the key specs (like with -inkey or -key params)" "\n\tand optionally certificates that verify this key", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam pubkeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--pubkey-pem", "--pubkey", "--pubkey-pem[:<name>] <file>" "\n\tload public key from PEM file", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam pubkeyDerParam = { xmlSecAppCmdLineTopicKeysMngr, "--pubkey-der", NULL, "--pubkey-der[:<name>] <file>" "\n\tload public key from DER file", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; /* openssl specific pubkey options */ static xmlSecAppCmdLineParam pubkeyOpensslStoreParam = { xmlSecAppCmdLineTopicKeysMngr, "--pubkey-openssl-store", NULL, "--pubkey-openssl-store[:<name>] <uri>" "\n\tload pubkey key and certs through OpenSSL ossl_store interface (e.g. from HSM)", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam pubkeyOpensslEngineParam = { xmlSecAppCmdLineTopicKeysMngr, "--pubkey-openssl-engine", NULL, "--pubkey-openssl-engine[:<name>] <openssl-engine>;<openssl-key-id>[,<crtfile>[,<crtfile>[...]]]" "\n\tload public key by OpenSSL ENGINE interface; specify the name of engine" "\n\t(like with -engine params), the key specs (like with -inkey or -key params)" "\n\tand optionally certificates that verify this key", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; #ifndef XMLSEC_NO_AES static xmlSecAppCmdLineParam aesKeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--aes-key", "--aeskey", "--aes-key[:<name>] <file>" "\n\tload AES key from binary file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; #endif /* XMLSEC_NO_AES */ #ifndef XMLSEC_NO_CONCATKDF static xmlSecAppCmdLineParam concatKdfKeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--concatkdfkey", "--concatkdf-key", "--concatkdf-key[:<name>] <file>" "\n\tload ConcatKDF key from binary file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; #endif /* XMLSEC_NO_CONCATKDF */ #ifndef XMLSEC_NO_DES static xmlSecAppCmdLineParam desKeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--des-key", "--deskey", "--des-key[:<name>] <file>" "\n\tload DES key from binary file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; #endif /* XMLSEC_NO_DES */ #ifndef XMLSEC_NO_HMAC static xmlSecAppCmdLineParam hmacKeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--hmac-key", "--hmackey", "--hmac-key[:<name>] <file>" "\n\tload HMAC key from binary file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam hmacMinOutputLenParam = { xmlSecAppCmdLineTopicKeysMngr, "--hmac-min-out-len", NULL, "--hmac-min-out-len <bits>" "\n\tsets minimum HMAC output length to <bits>", xmlSecAppCmdLineParamTypeNumber, xmlSecAppCmdLineParamFlagParamNameValue, NULL }; #endif /* XMLSEC_NO_HMAC */ #ifndef XMLSEC_NO_PBKDF2 static xmlSecAppCmdLineParam pbkdf2KeyParam = { xmlSecAppCmdLineTopicKeysMngr, "--pbkdf2key", "--pbkdf2-key", "--pbkdf2-key[:<name>] <file>" "\n\tload Pbkdf2 key from binary file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; #endif /* XMLSEC_NO_PBKDF2 */ static xmlSecAppCmdLineParam pwdParam = { xmlSecAppCmdLineTopicKeysMngr, "--pwd", NULL, "--pwd <password>" "\n\tthe password to use for reading keys and certs", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam enabledKeyDataParam = { xmlSecAppCmdLineTopicKeysMngr, "--enabled-key-data", NULL, "--enabled-key-data <list>" "\n\tcomma-separated list of key-data types to enable." "\n\tExample:" "\n\t rsa,key-value,x509 -> populates <RSAKeyValue> and keeps <X509Data>" "\n\t when <KeyValue/> and <X509Data/> placeholders" "\n\t are present in the template." "\n\tUse \"--list-key-data\" to view full list of registered key data klasses." "\n\tBy default, all registered key data are enabled.", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam enabledRetrievalMethodUrisParam = { xmlSecAppCmdLineTopicKeysMngr, "--enabled-retrieval-method-uris", NULL, "--enabled-retrieval-method-uris <list>" "\n\tcomma separated list of of the following values:" "\n\t\"empty\", \"same-doc\", \"local\",\"remote\" to restrict possible URI" "\n\tattribute values for the <dsig:RetrievalMethod> element.", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam enabledKeyInfoReferenceUrisParam = { xmlSecAppCmdLineTopicKeysMngr, "--enabled-key-info-reference-uris", NULL, "--enabled-key-info-reference-uris <list>" "\n\tcomma separated list of of the following values:" "\n\t\"empty\", \"same-doc\", \"local\",\"remote\" to restrict possible URI" "\n\tattribute values for the <dsig11:KeyInfoReference> element.", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam laxKeySearchParam = { xmlSecAppCmdLineTopicKeysMngr, "--lax-key-search", NULL, "--lax-key-search" "\n\tenable lax key search (e.g. by key type like \"rsa\") vs default strict key search" "\n\tmode using only information from <dsig:KeyInfo/> node (e.g. key name)", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam verifyKeysParam = { xmlSecAppCmdLineTopicKeysMngr, "--verify-keys", NULL, "--verify-keys" "\n\tforce verification of public/private keys loaded from the command: keys are required" "\n\tto have a key certificate that will be verified against the certificates in the key store", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; /**************************************************************** * * Common params * ***************************************************************/ static xmlSecAppCmdLineParam sessionKeyParam = { xmlSecAppCmdLineTopicDSigSign | xmlSecAppCmdLineTopicEncEncrypt, "--session-key", NULL, "--session-key <keyKlass>-<keySize>" "\n\tgenerate new session <keyKlass> key of <keySize> bits size" "\n\t(for example, \"--session des-192\" generates a new 192 bits" "\n\tDES key for DES3 encryption)", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam outputParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--output", "-o", "--output <filename>" "\n\twrite result document to file <filename>; the <filename> can" "\n\tbe a template and include '{inputfile}' which will be repaced" "\n\twith the input filename", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam nodeIdParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--node-id", NULL, "--node-id <id>" "\n\tset the operation start point to the node with given <id>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam nodeNameParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--node-name", NULL, "--node-name [<namespace-uri>:]<name>" "\n\tset the operation start point to the first node" "\n\twith given <name> and <namespace> URI", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam nodeXPathParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--node-xpath", NULL, "--node-xpath <expr>" "\n\tset the operation start point to the first node" "\n\tselected by the specified XPath expression", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam dtdFileParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--dtd-file", NULL, "--dtd-file <file>" "\n\tload the specified file as the DTD", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam printDebugParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--print-debug", NULL, "--print-debug" "\n\tprint debug information to stdout", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam printXmlDebugParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--print-xml-debug", NULL, "--print-xml-debug" "\n\tprint debug information to stdout in xml format", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam idAttrParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--id-attr", NULL, "--id-attr[:<attr-name>] [<node-namespace-uri>:]<node-name>" "\n\tadds attributes <attr-name> (default value \"id\") from all nodes" "\n\twith<node-name> and namespace <node-namespace-uri> to the list of" "\n\tknown ID attributes; this is a hack and if you can use DTD or schema" "\n\tto declare ID attributes instead (see \"--dtd-file\" option)", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam addIdAttrParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--add-id-attr", NULL, "--add-id-attr <id-attribute-name>" "\n\tadds attribute <id-attribute-name> to all nodes in the document;" "\n\tthis is a hack and if you can use DTD or schema to declare ID attributes" "\n\tinstead (see \"--dtd-file\" option)", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam xxeParam = { xmlSecAppCmdLineTopicAll, "--xxe", NULL, "--xxe" "\n\tenable External Entity resolution." "\n\tWARNING: this may allow the reading of arbitrary files and URLs," "\n\tcontrolled by the input XML document. Use with caution!", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam urlMapParam = { xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicEncCommon, "--url-map", NULL, "--url-map:<url> <file>" "\n\tmaps a given <url> to the given <file> for loading external resources", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; /**************************************************************** * * Common dsig params * ***************************************************************/ #ifndef XMLSEC_NO_XMLDSIG static xmlSecAppCmdLineParam ignoreManifestsParam = { xmlSecAppCmdLineTopicDSigCommon, "--ignore-manifests", NULL, "--ignore-manifests" "\n\tdo not process <dsig:Manifest> elements", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam storeReferencesParam = { xmlSecAppCmdLineTopicDSigCommon, "--store-references", NULL, "--store-references" "\n\tstore and print the result of <dsig:Reference/> element processing" "\n\tjust before calculating digest", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam storeSignaturesParam = { xmlSecAppCmdLineTopicDSigCommon, "--store-signatures", NULL, "--store-signatures" "\n\tstore and print the result of <dsig:Signature> processing" "\n\tjust before calculating signature", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam enabledRefUrisParam = { xmlSecAppCmdLineTopicDSigCommon, "--enabled-reference-uris", NULL, "--enabled-reference-uris <list>" "\n\tcomma separated list of of the following values:" "\n\t\"empty\", \"same-doc\", \"local\",\"remote\" to restrict possible URI" "\n\tattribute values for the <dsig:Reference> element", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam enableVisa3DHackParam = { xmlSecAppCmdLineTopicDSigCommon, "--enable-visa3d-hack", NULL, "--enable-visa3d-hack" "\n\tenables Visa3D protocol specific hack for URI attributes processing" "\n\twhen we are trying not to use XPath/XPointer engine; this is a hack" "\n\tand I don't know what else might be broken in your application when" "\n\tyou use it (also check \"--id-attr\" option because you might need it)", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; #endif /* XMLSEC_NO_XMLDSIG */ /**************************************************************** * * Enc params * ***************************************************************/ #ifndef XMLSEC_NO_XMLENC static xmlSecAppCmdLineParam enabledCipherRefUrisParam = { xmlSecAppCmdLineTopicEncCommon, "--enabled-cipher-reference-uris", NULL, "--enabled-cipher-reference-uris <list>" "\n\tcomma separated list of of the following values:" "\n\t\"empty\", \"same-doc\", \"local\",\"remote\" to restrict possible URI" "\n\tattribute values for the <enc:CipherReference> element", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam binaryDataParam = { xmlSecAppCmdLineTopicEncEncrypt, "--binary-data", "--binary", "--binary-data <file>" "\n\tbinary <file> to encrypt", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam xmlDataParam = { xmlSecAppCmdLineTopicEncEncrypt, "--xml-data", NULL, "--xml-data <file>" "\n\tXML <file> to encrypt", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagNone, NULL }; #endif /* XMLSEC_NO_XMLENC */ /**************************************************************** * * X509 params * ***************************************************************/ #ifndef XMLSEC_NO_X509 static xmlSecAppCmdLineParam pkcs12Param = { xmlSecAppCmdLineTopicKeysMngr, "--pkcs12", NULL, "--pkcs12[:<name>] <file>" "\n\tload load private key from pkcs12 file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam pkcs12PersistParam = { xmlSecAppCmdLineTopicKeysMngr, "--pkcs12-persist", NULL, "--pkcs12-persist" "\n\tpersist loaded private key", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam pubkeyCertParam = { xmlSecAppCmdLineTopicKeysMngr, "--pubkey-cert-pem", "--pubkey-cert", "--pubkey-cert-pem[:<name>] <file>" "\n\tload public key from PEM cert file", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam pubkeyCertDerParam = { xmlSecAppCmdLineTopicKeysMngr, "--pubkey-cert-der", NULL, "--pubkey-cert-der[:<name>] <file>" "\n\tload public key from DER cert file", xmlSecAppCmdLineParamTypeStringList, xmlSecAppCmdLineParamFlagParamNameValue | xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam trustedParam = { xmlSecAppCmdLineTopicX509Certs, "--trusted-pem", "--trusted", "--trusted-pem <file>" "\n\tload trusted (root) certificate from PEM file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam trustedDerParam = { xmlSecAppCmdLineTopicX509Certs, "--trusted-der", NULL, "--trusted-der <file>" "\n\tload trusted (root) certificate from DER file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam untrustedParam = { xmlSecAppCmdLineTopicX509Certs, "--untrusted-pem", "--untrusted", "--untrusted-pem <file>" "\n\tload untrusted certificate from PEM file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam untrustedDerParam = { xmlSecAppCmdLineTopicX509Certs, "--untrusted-der", NULL, "--untrusted-der <file>" "\n\tload untrusted certificate from DER file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam crlPemParam = { xmlSecAppCmdLineTopicX509Certs, "--crl-pem", "--crl", "--crl-pem <file>" "\n\tload CRLs from PEM file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam crlDerParam = { xmlSecAppCmdLineTopicX509Certs, "--crl-der", NULL, "--crl-der <file>" "\n\tload CRLs from DER file <file>", xmlSecAppCmdLineParamTypeString, xmlSecAppCmdLineParamFlagMultipleValues, NULL }; static xmlSecAppCmdLineParam verificationTimeParam = { xmlSecAppCmdLineTopicX509Certs, "--verification-time", NULL, "--verification-time <time>" "\n\tthe local time in \"YYYY-MM-DD HH:MM:SS\" format" "\n\tused certificates verification", xmlSecAppCmdLineParamTypeTime, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam verificationGmtTimeParam = { xmlSecAppCmdLineTopicX509Certs, "--verification-gmt-time", NULL, "--verification-gmt-time <time>" "\n\tthe GMT time in \"YYYY-MM-DD HH:MM:SS\" format" "\n\tused certificates verification", xmlSecAppCmdLineParamTypeGmtTime, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam X509SkipTimeChecksParam = { xmlSecAppCmdLineTopicX509Certs, "--X509-skip-time-checks", NULL, "--X509-skip-time-checks" "\n\tskip time checking of X509 certificates and CLRs", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam depthParam = { xmlSecAppCmdLineTopicX509Certs, "--depth", NULL, "--depth <number>" "\n\tmaximum certificates chain depth", xmlSecAppCmdLineParamTypeNumber, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam X509SkipStrictChecksParam = { xmlSecAppCmdLineTopicX509Certs, "--X509-skip-strict-checks", NULL, "--X509-skip-strict-checks" "\n\tskip strict checking of X509 data", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; static xmlSecAppCmdLineParam X509DontVerifyCerts = { xmlSecAppCmdLineTopicX509Certs, "--insecure", NULL, "--insecure" "\n\tdo not verify certificates", xmlSecAppCmdLineParamTypeFlag, xmlSecAppCmdLineParamFlagNone, NULL }; #endif /* XMLSEC_NO_X509 */ static xmlSecAppCmdLineParamPtr parameters[] = { /* common dsig params */ #ifndef XMLSEC_NO_XMLDSIG &ignoreManifestsParam, &storeReferencesParam, &storeSignaturesParam, &enabledRefUrisParam, &enableVisa3DHackParam, #ifndef XMLSEC_NO_HMAC &hmacMinOutputLenParam, #endif /* XMLSEC_NO_HMAC */ #endif /* XMLSEC_NO_XMLDSIG */ /* enc params */ #ifndef XMLSEC_NO_XMLENC &binaryDataParam, &xmlDataParam, &enabledCipherRefUrisParam, #endif /* XMLSEC_NO_XMLENC */ /* common dsig and enc parameters */ &sessionKeyParam, &outputParam, &printDebugParam, &printXmlDebugParam, &dtdFileParam, &nodeIdParam, &nodeNameParam, &nodeXPathParam, &idAttrParam, &addIdAttrParam, /* Keys Manager params */ &enabledKeyDataParam, &enabledRetrievalMethodUrisParam, &enabledKeyInfoReferenceUrisParam, &genKeyParam, &keysFileParam, &privkeyParam, &privkeyDerParam, &pkcs8PemParam, &pkcs8DerParam, &privkeyOpensslStoreParam, &privkeyOpensslEngineParam, &pubkeyParam, &pubkeyDerParam, &pubkeyOpensslStoreParam, &pubkeyOpensslEngineParam, &pwdParam, &laxKeySearchParam, &verifyKeysParam, #ifndef XMLSEC_NO_AES &aesKeyParam, #endif /* XMLSEC_NO_AES */ #ifndef XMLSEC_NO_CONCATKDF &concatKdfKeyParam, #endif /* XMLSEC_NO_CONCATKDF */ #ifndef XMLSEC_NO_DES &desKeyParam, #endif /* XMLSEC_NO_DES */ #ifndef XMLSEC_NO_HMAC &hmacKeyParam, #endif /* XMLSEC_NO_HMAC */ #ifndef XMLSEC_NO_PBKDF2 &pbkdf2KeyParam, #endif /* XMLSEC_NO_PBKDF2 */ #ifndef XMLSEC_NO_X509 &pkcs12Param, &pkcs12PersistParam, &pubkeyCertParam, &pubkeyCertDerParam, &trustedParam, &untrustedParam, &trustedDerParam, &untrustedDerParam, &crlPemParam, &crlDerParam, &verificationTimeParam, &verificationGmtTimeParam, &X509SkipTimeChecksParam, &depthParam, &X509SkipStrictChecksParam, &X509DontVerifyCerts, #endif /* XMLSEC_NO_X509 */ /* General configuration params */ &cryptoParam, &cryptoConfigParam, &verboseParam, &printCryptoErrorsParam, &repeatParam, &base64LineSizeParam, &transformBinChunkSizeParam, &xxeParam, &urlMapParam, &helpParam, /* MUST be the last one */ NULL }; typedef enum { xmlSecAppCommandUnknown = 0, xmlSecAppCommandHelp, xmlSecAppCommandListKeyData, xmlSecAppCommandCheckKeyData, xmlSecAppCommandListTransforms, xmlSecAppCommandCheckTransforms, xmlSecAppCommandVersion, xmlSecAppCommandKeys, xmlSecAppCommandSign, xmlSecAppCommandVerify, xmlSecAppCommandSignTmpl, xmlSecAppCommandEncrypt, xmlSecAppCommandDecrypt, xmlSecAppCommandEncryptTmpl } xmlSecAppCommand; typedef struct _xmlSecAppXmlData xmlSecAppXmlData, *xmlSecAppXmlDataPtr; struct _xmlSecAppXmlData { xmlDocPtr doc; xmlDtdPtr dtd; xmlNodePtr startNode; }; static xmlSecAppXmlDataPtr xmlSecAppXmlDataCreate (const char* filename, const xmlChar* defStartNodeName, const xmlChar* defStartNodeNs); static void xmlSecAppXmlDataDestroy (xmlSecAppXmlDataPtr data); static xmlSecAppCommand xmlSecAppParseCommand (const char* cmd, xmlSecAppCmdLineParamTopic* topics, xmlSecAppCommand* subCommand); static void xmlSecAppPrintHelp (xmlSecAppCommand command, xmlSecAppCmdLineParamTopic topics); #define xmlSecAppPrintUsage() xmlSecAppPrintHelp(xmlSecAppCommandUnknown, 0) static int xmlSecAppInit (void); static void xmlSecAppShutdown (void); static int xmlSecAppLoadKeys (void); static int xmlSecAppPrepareKeyInfoCtx (xmlSecKeyInfoCtxPtr ctx); #ifndef XMLSEC_NO_XMLDSIG static int xmlSecAppSignFile (const char* inputFileName, const char* outputFileNameTmpl); static int xmlSecAppVerifyFile (const char* inputFileName); #ifndef XMLSEC_NO_TMPL_TEST static int xmlSecAppSignTmpl (const char* outputFileNameTmpl); #endif /* XMLSEC_NO_TMPL_TEST */ static int xmlSecAppPrepareDSigCtx (xmlSecDSigCtxPtr dsigCtx); static void xmlSecAppPrintDSigCtx (xmlSecDSigCtxPtr dsigCtx); #endif /* XMLSEC_NO_XMLDSIG */ #ifndef XMLSEC_NO_XMLENC static int xmlSecAppEncryptFile (const char* inputFileName, const char* outputFileNameTmpl); static int xmlSecAppDecryptFile (const char* inputFileName, const char* outputFileNameTmpl); #ifndef XMLSEC_NO_TMPL_TEST static int xmlSecAppEncryptTmpl (const char* outputFileNameTmpl); #endif /* XMLSEC_NO_TMPL_TEST */ static int xmlSecAppPrepareEncCtx (xmlSecEncCtxPtr encCtx); static void xmlSecAppPrintEncCtx (xmlSecEncCtxPtr encCtx); #endif /* XMLSEC_NO_XMLENC */ static void xmlSecAppListKeyData (void); static int xmlSecAppCheckKeyData (const char * name); static void xmlSecAppListTransforms (void); static int xmlSecAppCheckTransform (const char * name); static xmlSecTransformUriType xmlSecAppGetUriType (const char* string); static xmlOutputBufferPtr xmlSecAppOpenFile (const char* filename, const char* encoding); static int xmlSecAppWriteResult (const char* inputFileName, const char* outputFileNameTmpl, xmlDocPtr doc, xmlSecBufferPtr buffer, const xmlChar* encoding); static int xmlSecAppAddIDAttr (xmlNodePtr cur, const xmlChar* attr, const xmlChar* node, const xmlChar* nsHref); static int xmlSecAppInputMatchCallback (char const * filename); static void* xmlSecAppInputOpenCallback (char const * filename); static int xmlSecAppInputReadCallback (void * context, char * buffer, int len); static int xmlSecAppInputCloseCallback (void * context); static int xmlSecAppExecute (xmlSecAppCommand command, const char** utf8_argv, int argc); #if defined(XMLSEC_WINDOWS) && defined(UNICODE) && defined(__MINGW32__) int wmain(int argc, wchar_t* argv[]); #endif /* defined(XMLSEC_WINDOWS) && defined(UNICODE) && defined(__MINGW32__) */ xmlSecKeysMngrPtr g_keysManager = NULL; int g_repeats = 1; int g_printDebug = 0; int g_printVerboseDebug = 0; int g_blockNetworkIO = 0; clock_t g_totalTime = 0; const char* g_xmlSecCryptoLibrary = NULL; const char* gOutputFilename = NULL; #if defined(XMLSEC_WINDOWS) && defined(UNICODE) int wmain(int argc, wchar_t *argv[]) { #else /* defined(XMLSEC_WINDOWS) && defined(UNICODE) */ int main(int argc, const char **argv) { #endif /* defined(XMLSEC_WINDOWS) && defined(UNICODE) */ #if defined(XMLSEC_WINDOWS) size_t utf8_argv_size; int ii; #endif /* defined(XMLSEC_WINDOWS) */ const char** utf8_argv = NULL; /* TODO: this should be xmlChar** but it will break things downstream */ xmlSecAppCmdLineParamTopic cmdLineTopics; xmlSecAppCommand command, subCommand; int pos; int res = 1; int ret; #if defined(_MSC_VER) && defined(_DEBUG) fprintf(stderr, "Enabling memory leaks detection\n"); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif /* */ #if defined(XMLSEC_WINDOWS) /* convert command line to UTF8 from locale or UNICODE */ utf8_argv_size = sizeof(char*) * (size_t)argc; utf8_argv = (const char**)xmlMalloc(utf8_argv_size); if(utf8_argv == NULL) { fprintf(stderr, "Error: can not allocate memory (" XMLSEC_SIZE_T_FMT " bytes)\n", utf8_argv_size); goto done; } memset((char**)utf8_argv, 0, utf8_argv_size); for(ii = 0; ii < argc; ++ii) { utf8_argv[ii] = (const char*)xmlSecWin32ConvertTstrToUtf8(argv[ii]); if(utf8_argv[ii] == NULL) { fprintf(stderr, "Error: can not convert command line parameter at position %d to UTF8\n", ii); goto done; } } #else /* defined(XMLSEC_WINDOWS) */ utf8_argv = argv; #endif /* defined(XMLSEC_WINDOWS) */ /* read the command (first argument) */ if(argc < 2) { fprintf(stderr, "Error: not enough arguments\n"); xmlSecAppPrintUsage(); goto done; } command = xmlSecAppParseCommand(utf8_argv[1], &cmdLineTopics, &subCommand); if(command == xmlSecAppCommandUnknown) { fprintf(stderr, "Error: unknown command \"%s\"\n", utf8_argv[1]); xmlSecAppPrintUsage(); res = 0; goto done; } /* do as much as we can w/o initialization */ if(command == xmlSecAppCommandHelp) { xmlSecAppPrintHelp(subCommand, cmdLineTopics); res = 0; goto done; } else if(command == xmlSecAppCommandVersion) { fprintf(stdout, "%s %s (%s)\n", PACKAGE, XMLSEC_VERSION, xmlSecGetDefaultCrypto()); res = 0; goto done; } /* parse command line */ pos = xmlSecAppCmdLineParamsListParse(parameters, cmdLineTopics, utf8_argv, argc, 2); if(pos < 0) { fprintf(stderr, "Error: invalid parameters\n"); xmlSecAppPrintUsage(); goto done; } /* is it a help request? */ if(xmlSecAppCmdLineParamIsSet(&helpParam)) { xmlSecAppPrintHelp(command, cmdLineTopics); return(0); } /* we need to have some files at the end */ switch(command) { case xmlSecAppCommandKeys: case xmlSecAppCommandSign: case xmlSecAppCommandVerify: case xmlSecAppCommandEncrypt: case xmlSecAppCommandDecrypt: if(pos >= argc) { fprintf(stderr, "Error: <file> parameter is required for this command\n"); xmlSecAppPrintUsage(); goto done; } break; default: break; } /* actual processing: skip all the parameters we already parsed */ ret = xmlSecAppExecute(command, utf8_argv + pos, argc - pos); if(ret < 0) { goto done; } /* sucecss! */ res = 0; done: xmlSecAppCmdLineParamsListClean(parameters); #if defined(XMLSEC_WINDOWS) if(utf8_argv != NULL) { for(ii = 0; ii < argc; ++ii) { if(utf8_argv[ii] != NULL) { xmlFree(BAD_CAST utf8_argv[ii]); utf8_argv[ii] = NULL; } } xmlFree(BAD_CAST utf8_argv); utf8_argv = NULL; } #endif /* defined(XMLSEC_WINDOWS) */ #if defined(_MSC_VER) && defined(_DEBUG) fprintf(stderr, "Printing memory leaks detected:\n"); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); if (_CrtDumpMemoryLeaks()) { fprintf(stderr, "Finished printing memory leaks detected\n"); return(1); } fprintf(stderr, "No memory leaks detected\n"); #endif /* defined(_MSC_VER) && defined(_CRTDBG_MAP_ALLOC) */ return(res); } static int xmlSecAppExecute(xmlSecAppCommand command, const char** utf8_argv, int argc) { const char* tmp = NULL; int res = - 1; int ii; /* now init the xmlsec and all other libs */ /* ignore "--crypto" if we don't have dynamic loading */ tmp = xmlSecAppCmdLineParamGetString(&cryptoParam); #if !defined(XMLSEC_NO_CRYPTO_DYNAMIC_LOADING) && defined(XMLSEC_CRYPTO_DYNAMIC_LOADING) if((tmp != NULL) && (strcmp(tmp, "default") != 0)) { g_xmlSecCryptoLibrary = tmp; } #else /* !defined(XMLSEC_NO_CRYPTO_DYNAMIC_LOADING) && defined(XMLSEC_CRYPTO_DYNAMIC_LOADING) */ if((tmp != NULL) && (xmlStrcmp(BAD_CAST tmp, xmlSecGetDefaultCrypto()) != 0) && (xmlStrcmp(BAD_CAST tmp, BAD_CAST "default") != 0)) { fprintf(stderr, "Error: dynamic xmlsec-crypto library loading is disabled and the only available crypto library is '%s'\n", xmlSecGetDefaultCrypto()); xmlSecAppPrintUsage(); goto done; } #endif /* !defined(XMLSEC_NO_CRYPTO_DYNAMIC_LOADING) && defined(XMLSEC_CRYPTO_DYNAMIC_LOADING) */ if(xmlSecAppInit() < 0) { fprintf(stderr, "Error: initialization failed\n"); xmlSecAppPrintUsage(); goto done; } /* enable XXE? */ if(xmlSecAppCmdLineParamIsSet(&xxeParam)) { /* new parser option XML_PARSE_NO_XXE available since 2.13.0 */ #if LIBXML_VERSION < 21300 xmlSecSetExternalEntityLoader(NULL); /* reset to libxml2's default handler */ #else /* LIBXML_VERSION < 21300 */ int options = xmlSecParserGetDefaultOptions(); options &= (~(XML_PARSE_NO_XXE)); xmlSecParserSetDefaultOptions(options); #endif /* LIBXML_VERSION < 21300 */ } /* enable verbose mode? */ if(xmlSecAppCmdLineParamIsSet(&verboseParam)) { xmlSecErrorsDefaultCallbackEnableOutput(1); } else { xmlSecErrorsDefaultCallbackEnableOutput(0); } /* enable deatiled crypto library errors on exit */ if(xmlSecAppCmdLineParamIsSet(&printCryptoErrorsParam)) { xmlSecErrorsPrintCryptoLibraryLogOnExitSet(1); } /* base64 line size */ if(xmlSecAppCmdLineParamIsSet(&base64LineSizeParam)) { int lineSize = xmlSecAppCmdLineParamGetInt(&base64LineSizeParam, 0); if(lineSize <= 0) { fprintf(stderr, "Error: base64 line size should be greater than zero\n"); xmlSecAppPrintUsage(); goto done; } xmlSecBase64SetDefaultLineSize(lineSize); } /* transform bin chunk size */ if(xmlSecAppCmdLineParamIsSet(&transformBinChunkSizeParam)) { int chunkSize = xmlSecAppCmdLineParamGetInt(&transformBinChunkSizeParam, 0); if(chunkSize <= 0) { fprintf(stderr, "Error: transform binary chunk size should be greater than zero\n"); xmlSecAppPrintUsage(); goto done; } xmlSecTransformCtxSetDefaultBinaryChunkSize((xmlSecSize)chunkSize); } /* load keys */ if(xmlSecAppLoadKeys() < 0) { fprintf(stderr, "Error: keys manager creation failed\n"); xmlSecAppPrintUsage(); goto done; } /* get the "g_repeats" number */ if(xmlSecAppCmdLineParamIsSet(&repeatParam) && (xmlSecAppCmdLineParamGetInt(&repeatParam, 1) > 0)) { g_repeats = xmlSecAppCmdLineParamGetInt(&repeatParam, 1); } /* get the output file */ gOutputFilename = xmlSecAppCmdLineParamGetString(&outputParam); /* execute requested number of times */ for(; g_repeats > 0; --g_repeats) { switch(command) { case xmlSecAppCommandListKeyData: xmlSecAppListKeyData(); break; case xmlSecAppCommandCheckKeyData: for(ii = 0; ii < argc; ++ii) { if(xmlSecAppCheckKeyData(utf8_argv[ii]) < 0) { fprintf(stderr, "Error: key data \"%s\" not found\n", utf8_argv[ii]); goto done; } else { fprintf(stdout, "Key data \"%s\" found\n", utf8_argv[ii]); } } break; case xmlSecAppCommandListTransforms: xmlSecAppListTransforms(); break; case xmlSecAppCommandCheckTransforms: for(ii = 0; ii < argc; ++ii) { if(xmlSecAppCheckTransform(utf8_argv[ii]) < 0) { fprintf(stderr, "Error: transform \"%s\" not found\n", utf8_argv[ii]); goto done; } else { fprintf(stdout, "Transforms \"%s\" found\n", utf8_argv[ii]); } } break; case xmlSecAppCommandKeys: for(ii = 0; ii < argc; ++ii) { if(xmlSecAppCryptoSimpleKeysMngrSave(g_keysManager, utf8_argv[ii], xmlSecKeyDataTypeAny) < 0) { fprintf(stderr, "Error: failed to save keys to file \"%s\"\n", utf8_argv[ii]); goto done; } } break; #ifndef XMLSEC_NO_XMLDSIG case xmlSecAppCommandSign: for(ii = 0; ii < argc; ++ii) { if(xmlSecAppSignFile(utf8_argv[ii], gOutputFilename) < 0) { fprintf(stderr, "Error: failed to sign file \"%s\"\n", utf8_argv[ii]); goto done; } } break; case xmlSecAppCommandVerify: for(ii = 0; ii < argc; ++ii) { if(xmlSecAppVerifyFile(utf8_argv[ii]) < 0) { fprintf(stderr, "Error: failed to verify file \"%s\"\n", utf8_argv[ii]); goto done; } } break; #ifndef XMLSEC_NO_TMPL_TEST case xmlSecAppCommandSignTmpl: if(xmlSecAppSignTmpl(gOutputFilename) < 0) { fprintf(stderr, "Error: failed to create and sign template\n"); goto done; } break; #endif /* XMLSEC_NO_TMPL_TEST */ #endif /* XMLSEC_NO_XMLDSIG */ #ifndef XMLSEC_NO_XMLENC case xmlSecAppCommandEncrypt: for(ii = 0; ii < argc; ++ii) { if(xmlSecAppEncryptFile(utf8_argv[ii], gOutputFilename) < 0) { fprintf(stderr, "Error: failed to encrypt file with template \"%s\"\n", utf8_argv[ii]); goto done; } } break; case xmlSecAppCommandDecrypt: for(ii = 0; ii < argc; ++ii) { if(xmlSecAppDecryptFile(utf8_argv[ii], gOutputFilename) < 0) { fprintf(stderr, "Error: failed to decrypt file \"%s\"\n", utf8_argv[ii]); goto done; } } break; #ifndef XMLSEC_NO_TMPL_TEST case xmlSecAppCommandEncryptTmpl: if(xmlSecAppEncryptTmpl(gOutputFilename) < 0) { fprintf(stderr, "Error: failed to create and encrypt template\n"); goto done; } break; #endif /* XMLSEC_NO_TMPL_TEST */ #endif /* XMLSEC_NO_XMLENC */ default: fprintf(stderr, "Error: invalid command %d\n", (int)command); xmlSecAppPrintUsage(); goto done; } } /* print perf stats results */ if(xmlSecAppCmdLineParamIsSet(&repeatParam) && (xmlSecAppCmdLineParamGetInt(&repeatParam, 1) > 0)) { long double msecs; g_repeats = xmlSecAppCmdLineParamGetInt(&repeatParam, 1); msecs = (1000 * g_totalTime) / (long double)CLOCKS_PER_SEC; fprintf(stderr, "Executed %d tests in %.2Lf msec\n", g_repeats, msecs); } /* success! */ res = 0; done: if(g_keysManager != NULL) { xmlSecKeysMngrDestroy(g_keysManager); g_keysManager = NULL; } xmlSecAppShutdown(); return(res); } #ifndef XMLSEC_NO_XMLDSIG static int xmlSecAppSignFile(const char* inputFileName, const char* outputFileNameTmpl) { xmlSecAppXmlDataPtr data = NULL; xmlSecDSigCtx dsigCtx; clock_t start_time; int res = -1; if(inputFileName == NULL) { fprintf(stderr, "Error: input filename is not specified\n"); return(-1); } if(xmlSecDSigCtxInitialize(&dsigCtx, g_keysManager) < 0) { fprintf(stderr, "Error: dsig context initialization failed\n"); return(-1); } if(xmlSecAppPrepareDSigCtx(&dsigCtx) < 0) { fprintf(stderr, "Error: dsig context preparation failed\n"); goto done; } /* parse template and select start node */ data = xmlSecAppXmlDataCreate(inputFileName, xmlSecNodeSignature, xmlSecDSigNs); if(data == NULL) { fprintf(stderr, "Error: failed to load template \"%s\"\n", inputFileName); goto done; } /* sign */ start_time = clock(); if(xmlSecDSigCtxSign(&dsigCtx, data->startNode) < 0) { /* caller will print the error */ goto done; } g_totalTime += clock() - start_time; /* return an error if siganture failed */ if(dsigCtx.status != xmlSecDSigStatusSucceeded) { goto done; } if(g_repeats <= 1) { int ret; ret = xmlSecAppWriteResult(inputFileName, outputFileNameTmpl, data->doc, NULL, data->doc->encoding); if(ret < 0) { goto done; } } res = 0; done: fprintf(stderr, "Signature status: %s\n", xmlSecDSigCtxGetStatusString(dsigCtx.status)); if((dsigCtx.status == xmlSecDSigStatusInvalid) && (dsigCtx.failureReason != xmlSecDSigFailureReasonUnknown)) { fprintf(stderr, "Failure reason: %s\n", xmlSecDSigCtxGetFailureReasonString(dsigCtx.failureReason)); } /* print debug info if requested */ if(xmlSecAppCmdLineParamIsSet(&verboseParam)) { xmlSecAppPrintDSigCtx(&dsigCtx); } xmlSecDSigCtxFinalize(&dsigCtx); if(data != NULL) { xmlSecAppXmlDataDestroy(data); } return(res); } static int xmlSecAppVerifyFile(const char* inputFileName) { xmlSecAppXmlDataPtr data = NULL; xmlSecDSigCtx dsigCtx; clock_t start_time; int res = -1; if(inputFileName == NULL) { fprintf(stderr, "Error: input filename is not specified\n"); return(-1); } if(xmlSecDSigCtxInitialize(&dsigCtx, g_keysManager) < 0) { fprintf(stderr, "Error: dsig context initialization failed\n"); return(-1); } if(xmlSecAppPrepareDSigCtx(&dsigCtx) < 0) { fprintf(stderr, "Error: dsig context preparation failed\n"); goto done; } /* parse template and select start node */ data = xmlSecAppXmlDataCreate(inputFileName, xmlSecNodeSignature, xmlSecDSigNs); if(data == NULL) { fprintf(stderr, "Error: failed to load document \"%s\"\n", inputFileName); goto done; } /* sign */ start_time = clock(); if(xmlSecDSigCtxVerify(&dsigCtx, data->startNode) < 0) { /* caller will print the error */ goto done; } g_totalTime += clock() - start_time; /* return an error if verification failed */ if(dsigCtx.status != xmlSecDSigStatusSucceeded) { goto done; } res = 0; done: fprintf(stderr, "Verification status: %s\n", xmlSecDSigCtxGetStatusString(dsigCtx.status)); if((dsigCtx.status == xmlSecDSigStatusInvalid) && (dsigCtx.failureReason != xmlSecDSigFailureReasonUnknown)) { fprintf(stderr, "Failure reason: %s\n", xmlSecDSigCtxGetFailureReasonString(dsigCtx.failureReason)); } /* print debug info if requested */ if(xmlSecAppCmdLineParamIsSet(&verboseParam)) { xmlSecDSigReferenceCtxPtr dsigRefCtx; xmlSecSize good, i, size; /* print stats about # of good/bad references/manifests */ size = xmlSecPtrListGetSize(&(dsigCtx.signedInfoReferences)); for(i = good = 0; i < size; ++i) { dsigRefCtx = (xmlSecDSigReferenceCtxPtr)xmlSecPtrListGetItem(&(dsigCtx.signedInfoReferences), i); if(dsigRefCtx == NULL) { fprintf(stderr,"Error: reference ctx is null\n"); goto done; } if(dsigRefCtx->status == xmlSecDSigStatusSucceeded) { ++good; } } fprintf(stderr, "SignedInfo References (ok/all): " XMLSEC_SIZE_FMT "/" XMLSEC_SIZE_FMT "\n", good, size); size = xmlSecPtrListGetSize(&(dsigCtx.manifestReferences)); for(i = good = 0; i < size; ++i) { dsigRefCtx = (xmlSecDSigReferenceCtxPtr)xmlSecPtrListGetItem(&(dsigCtx.manifestReferences), i); if(dsigRefCtx == NULL) { fprintf(stderr,"Error: reference ctx is null\n"); goto done; } if(dsigRefCtx->status == xmlSecDSigStatusSucceeded) { ++good; } } fprintf(stderr, "Manifests References (ok/all): " XMLSEC_SIZE_FMT "/" XMLSEC_SIZE_FMT "\n", good, size); xmlSecAppPrintDSigCtx(&dsigCtx); } xmlSecDSigCtxFinalize(&dsigCtx); if(data != NULL) { xmlSecAppXmlDataDestroy(data); } return(res); } #ifndef XMLSEC_NO_TMPL_TEST static int xmlSecAppSignTmpl(const char* outputFileNameTmpl) { xmlDocPtr doc = NULL; xmlNodePtr cur; xmlSecDSigCtx dsigCtx; clock_t start_time; int res = -1; if(xmlSecDSigCtxInitialize(&dsigCtx, g_keysManager) < 0) { fprintf(stderr, "Error: dsig context initialization failed\n"); return(-1); } if(xmlSecAppPrepareDSigCtx(&dsigCtx) < 0) { fprintf(stderr, "Error: dsig context preparation failed\n"); goto done; } /* prepare template */ doc = xmlNewDoc(BAD_CAST "1.0"); if(doc == NULL) { fprintf(stderr, "Error: failed to create doc\n"); goto done; } cur = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14NId, xmlSecTransformHmacSha256Id, NULL); if(cur == NULL) { fprintf(stderr, "Error: failed to create Signature node\n"); goto done; } xmlDocSetRootElement(doc, cur); /* set hmac signature length */ cur = xmlSecTmplSignatureGetSignMethodNode(xmlDocGetRootElement(doc)); if(cur == NULL) { fprintf(stderr, "Error: failed to find SignatureMethod node\n"); goto done; } if(xmlSecTmplTransformAddHmacOutputLength(cur, 93) < 0) { fprintf(stderr, "Error: failed to set hmac length\n"); goto done; } cur = xmlSecTmplSignatureAddReference(xmlDocGetRootElement(doc), xmlSecTransformSha256Id, BAD_CAST "ref1", NULL, NULL); if(cur == NULL) { fprintf(stderr, "Error: failed to add Reference node\n"); goto done; } cur = xmlSecTmplReferenceAddTransform(cur, xmlSecTransformXPath2Id); if(cur == NULL) { fprintf(stderr, "Error: failed to add XPath transform\n"); goto done; } if(xmlSecTmplTransformAddXPath2(cur, BAD_CAST "intersect", BAD_CAST "//*[@Id='object1']", NULL) < 0) { fprintf(stderr, "Error: failed to set XPath expression\n"); goto done; } cur = xmlSecTmplSignatureAddObject(xmlDocGetRootElement(doc), BAD_CAST "object1", NULL, NULL); if(cur == NULL) { fprintf(stderr, "Error: failed to add Object node\n"); goto done; } xmlNodeSetContent(cur, BAD_CAST "This is signed data"); /* add key information */ cur = xmlSecTmplSignatureEnsureKeyInfo(xmlDocGetRootElement(doc), NULL); if(cur == NULL) { fprintf(stderr, "Error: failed to add KeyInfo node\n"); goto done; } if(xmlSecTmplKeyInfoAddKeyName(cur, NULL) == NULL) { fprintf(stderr, "Error: failed to add KeyName node\n"); goto done; } /* sign */ start_time = clock(); if(xmlSecDSigCtxSign(&dsigCtx, xmlDocGetRootElement(doc)) < 0) { /* caller will print the error */ goto done; } g_totalTime += clock() - start_time; /* return an error if siganture failed */ if(dsigCtx.status != xmlSecDSigStatusSucceeded) { goto done; } if(g_repeats <= 1) { int ret; ret = xmlSecAppWriteResult(NULL, outputFileNameTmpl, doc, NULL, doc->encoding); if(ret < 0) { goto done; } } res = 0; done: fprintf(stderr, "Signature status: %s\n", xmlSecDSigCtxGetStatusString(dsigCtx.status)); if((dsigCtx.status == xmlSecDSigStatusInvalid) && (dsigCtx.failureReason != xmlSecDSigFailureReasonUnknown)) { fprintf(stderr, "Failure reason: %s\n", xmlSecDSigCtxGetFailureReasonString(dsigCtx.failureReason)); } /* print debug info if requested */ if(xmlSecAppCmdLineParamIsSet(&verboseParam)) { xmlSecAppPrintDSigCtx(&dsigCtx); } xmlSecDSigCtxFinalize(&dsigCtx); if(doc != NULL) { xmlFreeDoc(doc); } return(res); } #endif /* XMLSEC_NO_TMPL_TEST */ static int xmlSecAppPrepareDSigCtx(xmlSecDSigCtxPtr dsigCtx) { if(dsigCtx == NULL) { fprintf(stderr, "Error: dsig context is null\n"); return(-1); } /* set key info params */ if(xmlSecAppPrepareKeyInfoCtx(&(dsigCtx->keyInfoReadCtx)) < 0) { fprintf(stderr, "Error: failed to prepare read key info context\n"); return(-1); } if(xmlSecAppPrepareKeyInfoCtx(&(dsigCtx->keyInfoWriteCtx)) < 0) { fprintf(stderr, "Error: failed to prepare write key info context\n"); return(-1); } if(xmlSecAppCmdLineParamGetString(&sessionKeyParam) != NULL) { dsigCtx->signKey = xmlSecAppCryptoKeyGenerate(xmlSecAppCmdLineParamGetString(&sessionKeyParam), NULL, xmlSecKeyDataTypeSession); if(dsigCtx->signKey == NULL) { fprintf(stderr, "Error: failed to generate a session key \"%s\"\n", xmlSecAppCmdLineParamGetString(&sessionKeyParam)); return(-1); } } /* set dsig params */ if(xmlSecAppCmdLineParamIsSet(&ignoreManifestsParam)) { dsigCtx->flags |= XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS; } if(xmlSecAppCmdLineParamIsSet(&storeReferencesParam)) { dsigCtx->flags |= XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES | XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES; g_printDebug = 1; } if(xmlSecAppCmdLineParamIsSet(&storeSignaturesParam)) { dsigCtx->flags |= XMLSEC_DSIG_FLAGS_STORE_SIGNATURE; g_printDebug = 1; } if(xmlSecAppCmdLineParamIsSet(&enableVisa3DHackParam)) { dsigCtx->flags |= XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK; } #ifndef XMLSEC_NO_HMAC if(xmlSecAppCmdLineParamIsSet(&hmacMinOutputLenParam)) { int minHmacOutLen = (int)xmlSecTransformHmacGetMinOutputBitsSize(); minHmacOutLen = xmlSecAppCmdLineParamGetInt(&hmacMinOutputLenParam, minHmacOutLen); xmlSecTransformHmacSetMinOutputBitsSize((xmlSecSize)minHmacOutLen); } #endif /* XMLSEC_NO_HMAC */ if(xmlSecAppCmdLineParamGetStringList(&enabledRefUrisParam) != NULL) { dsigCtx->enabledReferenceUris = xmlSecAppGetUriType( xmlSecAppCmdLineParamGetStringList(&enabledRefUrisParam)); if(dsigCtx->enabledReferenceUris == xmlSecTransformUriTypeNone) { fprintf(stderr, "Error: failed to parse \"%s\"\n", xmlSecAppCmdLineParamGetStringList(&enabledRefUrisParam)); return(-1); } } return(0); } static void xmlSecAppPrintDSigCtx(xmlSecDSigCtxPtr dsigCtx) { if(dsigCtx == NULL) { return; } /* print debug info if requested */ if((g_printDebug != 0) || xmlSecAppCmdLineParamIsSet(&printDebugParam)) { xmlSecDSigCtxDebugDump(dsigCtx, stdout); } if(xmlSecAppCmdLineParamIsSet(&printXmlDebugParam)) { xmlSecDSigCtxDebugXmlDump(dsigCtx, stdout); } } #endif /* XMLSEC_NO_XMLDSIG */ #ifndef XMLSEC_NO_XMLENC static int xmlSecAppEncryptFile(const char* inputFileName, const char* outputFileNameTmpl) { xmlSecAppXmlDataPtr data = NULL; xmlSecEncCtx encCtx; xmlDocPtr doc = NULL; xmlNodePtr startTmplNode; clock_t start_time; int res = -1; if(inputFileName == NULL) { fprintf(stderr, "Error: input filename is not specified\n"); return(-1); } if(xmlSecEncCtxInitialize(&encCtx, g_keysManager) < 0) { fprintf(stderr, "Error: enc context initialization failed\n"); return(-1); } if(xmlSecAppPrepareEncCtx(&encCtx) < 0) { fprintf(stderr, "Error: enc context preparation failed\n"); goto done; } /* parse doc and find template node */ doc = xmlSecParseFile(inputFileName); if(doc == NULL) { fprintf(stderr, "Error: failed to parse xml file \"%s\"\n", inputFileName); goto done; } startTmplNode = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs); if(startTmplNode == NULL) { fprintf(stderr, "Error: failed to find default node with name=\"%s\"\n", xmlSecNodeEncryptedData); goto done; } if(xmlSecAppCmdLineParamGetString(&binaryDataParam) != NULL) { /* encrypt */ start_time = clock(); if(xmlSecEncCtxUriEncrypt(&encCtx, startTmplNode, BAD_CAST xmlSecAppCmdLineParamGetString(&binaryDataParam)) < 0) { fprintf(stderr, "Error: failed to encrypt file \"%s\"\n", xmlSecAppCmdLineParamGetString(&binaryDataParam)); goto done; } g_totalTime += clock() - start_time; } else if(xmlSecAppCmdLineParamGetString(&xmlDataParam) != NULL) { /* parse file and select node for encryption */ data = xmlSecAppXmlDataCreate(xmlSecAppCmdLineParamGetString(&xmlDataParam), NULL, NULL); if(data == NULL) { fprintf(stderr, "Error: failed to load file \"%s\"\n", xmlSecAppCmdLineParamGetString(&xmlDataParam)); goto done; } /* encrypt */ start_time = clock(); if(xmlSecEncCtxXmlEncrypt(&encCtx, startTmplNode, data->startNode) < 0) { fprintf(stderr, "Error: failed to encrypt xml file \"%s\"\n", xmlSecAppCmdLineParamGetString(&xmlDataParam)); goto done; } g_totalTime += clock() - start_time; } else { fprintf(stderr, "Error: encryption data not specified (use \"--xml-data\" or \"--binary-data\" options)\n"); goto done; } /* print out result only once per execution */ if(g_repeats <= 1) { if(encCtx.resultReplaced) { if(xmlSecAppWriteResult(inputFileName, outputFileNameTmpl, (data != NULL) ? data->doc : doc, NULL, (data != NULL) ? data->doc->encoding : doc->encoding) < 0) { goto done; } } else { if(xmlSecAppWriteResult(inputFileName, outputFileNameTmpl, NULL, encCtx.result, (data != NULL) ? data->doc->encoding : doc->encoding) < 0) { goto done; } } } res = 0; done: if(encCtx.failureReason != xmlSecEncFailureReasonUnknown) { fprintf(stderr, "Failure reason: %s\n", xmlSecEncCtxGetFailureReasonString(encCtx.failureReason)); } /* print debug info if requested */ if(xmlSecAppCmdLineParamIsSet(&verboseParam)) { xmlSecAppPrintEncCtx(&encCtx); } xmlSecEncCtxFinalize(&encCtx); if(data != NULL) { xmlSecAppXmlDataDestroy(data); } if(doc != NULL) { xmlFreeDoc(doc); } return(res); } static int xmlSecAppDecryptFile(const char* inputFileName, const char* outputFileNameTmpl) { xmlSecAppXmlDataPtr data = NULL; xmlSecEncCtx encCtx; clock_t start_time; int res = -1; if(inputFileName == NULL) { fprintf(stderr, "Error: input filename is not specified\n"); return(-1); } if(xmlSecEncCtxInitialize(&encCtx, g_keysManager) < 0) { fprintf(stderr, "Error: enc context initialization failed\n"); return(-1); } if(xmlSecAppPrepareEncCtx(&encCtx) < 0) { fprintf(stderr, "Error: enc context preparation failed\n"); goto done; } /* parse template and select start node */ data = xmlSecAppXmlDataCreate(inputFileName, xmlSecNodeEncryptedData, xmlSecEncNs); if(data == NULL) { fprintf(stderr, "Error: failed to load template \"%s\"\n", inputFileName); goto done; } start_time = clock(); if(xmlSecEncCtxDecrypt(&encCtx, data->startNode) < 0) { fprintf(stderr, "Error: failed to decrypt file\n"); goto done; } g_totalTime += clock() - start_time; /* print out result only once per execution */ if(g_repeats <= 1) { if(encCtx.resultReplaced) { if(xmlSecAppWriteResult(inputFileName, outputFileNameTmpl, data->doc, NULL, data->doc->encoding) < 0) { goto done; } } else { if(xmlSecAppWriteResult(inputFileName, outputFileNameTmpl, NULL, encCtx.result, data->doc->encoding) < 0) { goto done; } } } res = 0; done: if(encCtx.failureReason != xmlSecEncFailureReasonUnknown) { fprintf(stderr, "Failure reason: %s\n", xmlSecEncCtxGetFailureReasonString(encCtx.failureReason)); } /* print debug info if requested */ if(xmlSecAppCmdLineParamIsSet(&verboseParam)) { xmlSecAppPrintEncCtx(&encCtx); } xmlSecEncCtxFinalize(&encCtx); if(data != NULL) { xmlSecAppXmlDataDestroy(data); } return(res); } #ifndef XMLSEC_NO_TMPL_TEST static int xmlSecAppEncryptTmpl(const char* outputFileNameTmpl) { const xmlChar data[] = "Hello, World!"; xmlSecEncCtx encCtx; xmlDocPtr doc = NULL; xmlNodePtr cur; clock_t start_time; int res = -1; if(xmlSecEncCtxInitialize(&encCtx, g_keysManager) < 0) { fprintf(stderr, "Error: enc context initialization failed\n"); return(-1); } if(xmlSecAppPrepareEncCtx(&encCtx) < 0) { fprintf(stderr, "Error: enc context preparation failed\n"); goto done; } /* prepare template */ doc = xmlNewDoc(BAD_CAST "1.0"); if(doc == NULL) { fprintf(stderr, "Error: failed to create doc\n"); goto done; } cur = xmlSecTmplEncDataCreate(doc, xmlSecTransformAes256CbcId, NULL, NULL, NULL, NULL); if(cur == NULL) { fprintf(stderr, "Error: failed to encryption template\n"); goto done; } xmlDocSetRootElement(doc, cur); if(xmlSecTmplEncDataEnsureCipherValue(xmlDocGetRootElement(doc)) == NULL) { fprintf(stderr, "Error: failed to add CipherValue node\n"); goto done; } /* add key information */ cur = xmlSecTmplEncDataEnsureKeyInfo(xmlDocGetRootElement(doc), NULL); if(cur == NULL) { fprintf(stderr, "Error: failed to add KeyInfo node\n"); goto done; } if(xmlSecTmplKeyInfoAddKeyName(cur, NULL) == NULL) { fprintf(stderr, "Error: failed to add KeyName node\n"); goto done; } /* encrypt */ start_time = clock(); if(xmlSecEncCtxBinaryEncrypt(&encCtx, xmlDocGetRootElement(doc), (const xmlSecByte*)data, xmlSecStrlen(data)) < 0) { fprintf(stderr, "Error: failed to encrypt data\n"); goto done; } g_totalTime += clock() - start_time; /* print out result only once per execution */ if(g_repeats <= 1) { if(encCtx.resultReplaced) { if(xmlSecAppWriteResult(NULL, outputFileNameTmpl, doc, NULL, doc->encoding) < 0) { goto done; } } else { if(xmlSecAppWriteResult(NULL, outputFileNameTmpl, NULL, encCtx.result, doc->encoding) < 0) { goto done; } } } res = 0; done: if(encCtx.failureReason != xmlSecEncFailureReasonUnknown) { fprintf(stderr, "Failure reason: %s\n", xmlSecEncCtxGetFailureReasonString(encCtx.failureReason)); } /* print debug info if requested */ if(xmlSecAppCmdLineParamIsSet(&verboseParam)) { xmlSecAppPrintEncCtx(&encCtx); } xmlSecEncCtxFinalize(&encCtx); if(doc != NULL) { xmlFreeDoc(doc); } return(res); } #endif /* XMLSEC_NO_TMPL_TEST */ static int xmlSecAppPrepareEncCtx(xmlSecEncCtxPtr encCtx) { if(encCtx == NULL) { fprintf(stderr, "Error: enc context is null\n"); return(-1); } /* set key info params */ if(xmlSecAppPrepareKeyInfoCtx(&(encCtx->keyInfoReadCtx)) < 0) { fprintf(stderr, "Error: failed to prepare read key info context\n"); return(-1); } if(xmlSecAppPrepareKeyInfoCtx(&(encCtx->keyInfoWriteCtx)) < 0) { fprintf(stderr, "Error: failed to prepare write key info context\n"); return(-1); } if(xmlSecAppCmdLineParamGetString(&sessionKeyParam) != NULL) { encCtx->encKey = xmlSecAppCryptoKeyGenerate(xmlSecAppCmdLineParamGetString(&sessionKeyParam), NULL, xmlSecKeyDataTypeSession); if(encCtx->encKey == NULL) { fprintf(stderr, "Error: failed to generate a session key \"%s\"\n", xmlSecAppCmdLineParamGetString(&sessionKeyParam)); return(-1); } } if(xmlSecAppCmdLineParamGetStringList(&enabledCipherRefUrisParam) != NULL) { encCtx->transformCtx.enabledUris = xmlSecAppGetUriType( xmlSecAppCmdLineParamGetStringList(&enabledCipherRefUrisParam)); if(encCtx->transformCtx.enabledUris == xmlSecTransformUriTypeNone) { fprintf(stderr, "Error: failed to parse \"%s\"\n", xmlSecAppCmdLineParamGetStringList(&enabledCipherRefUrisParam)); return(-1); } } return(0); } static void xmlSecAppPrintEncCtx(xmlSecEncCtxPtr encCtx) { if(encCtx == NULL) { return; } /* print debug info if requested */ if((g_printDebug != 0) || xmlSecAppCmdLineParamIsSet(&printDebugParam)) { xmlSecEncCtxDebugDump(encCtx, stdout); } if(xmlSecAppCmdLineParamIsSet(&printXmlDebugParam)) { xmlSecEncCtxDebugXmlDump(encCtx, stdout); } } #endif /* XMLSEC_NO_XMLENC */ static void xmlSecAppListKeyData(void) { fprintf(stdout, "Registered key data klasses:\n"); xmlSecKeyDataIdListDebugDump(xmlSecKeyDataIdsGet(), stdout); } static int xmlSecAppCheckKeyData(const char * name) { if(xmlSecKeyDataIdListFindByName(xmlSecKeyDataIdsGet(), BAD_CAST name, xmlSecKeyDataUsageAny) == xmlSecKeyDataIdUnknown) { return -1; } return 0; } static void xmlSecAppListTransforms(void) { fprintf(stdout, "Registered transform klasses:\n"); xmlSecTransformIdListDebugDump(xmlSecTransformIdsGet(), stdout); } static int xmlSecAppCheckTransform(const char * name) { if(xmlSecTransformIdListFindByName(xmlSecTransformIdsGet(), BAD_CAST name, xmlSecTransformUsageAny) == xmlSecTransformIdUnknown) { return -1; } return 0; } static int xmlSecAppPrepareKeyInfoCtx(xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecAppCmdLineValuePtr value; int ret; xmlSecKeyDataId dataId; const char* p; if(keyInfoCtx == NULL) { fprintf(stderr, "Error: key info context is null\n"); return(-1); } #ifndef XMLSEC_NO_X509 if(xmlSecAppCmdLineParamIsSet(&verificationTimeParam)) { keyInfoCtx->certsVerificationTime = xmlSecAppCmdLineParamGetTime(&verificationTimeParam, 0); } if(xmlSecAppCmdLineParamIsSet(&verificationGmtTimeParam)) { keyInfoCtx->certsVerificationTime = xmlSecAppCmdLineParamGetTime(&verificationGmtTimeParam, 0); } if(xmlSecAppCmdLineParamIsSet(&X509SkipTimeChecksParam)) { keyInfoCtx->flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_TIME_CHECKS; } if(xmlSecAppCmdLineParamIsSet(&depthParam)) { keyInfoCtx->certsVerificationDepth = xmlSecAppCmdLineParamGetInt(&depthParam, 0); } if(xmlSecAppCmdLineParamIsSet(&X509SkipStrictChecksParam)) { keyInfoCtx->flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_SKIP_STRICT_CHECKS; } if(xmlSecAppCmdLineParamIsSet(&X509DontVerifyCerts)) { keyInfoCtx->flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; } #endif /* XMLSEC_NO_X509 */ if(xmlSecAppCmdLineParamIsSet(&laxKeySearchParam)) { keyInfoCtx->flags |= XMLSEC_KEYINFO_FLAGS_LAX_KEY_SEARCH; } /* read enabled key data list */ for(value = enabledKeyDataParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", enabledKeyDataParam.fullName); return(-1); } for(p = value->strListValue; (p != NULL) && ((*p) != '\0'); p += strlen(p) + 1) { dataId = xmlSecKeyDataIdListFindByName(xmlSecKeyDataIdsGet(), BAD_CAST p, xmlSecKeyDataUsageAny); if(dataId == xmlSecKeyDataIdUnknown) { fprintf(stderr, "Error: key data \"%s\" is unknown.\n", p); return(-1); } ret = xmlSecPtrListAdd(&(keyInfoCtx->enabledKeyData), (const xmlSecPtr)dataId); if(ret < 0) { fprintf(stderr, "Error: failed to enable key data \"%s\".\n", p); return(-1); } } } /* read enabled RetrievalMethod uris */ if(xmlSecAppCmdLineParamGetStringList(&enabledRetrievalMethodUrisParam) != NULL) { keyInfoCtx->retrievalMethodCtx.enabledUris = xmlSecAppGetUriType( xmlSecAppCmdLineParamGetStringList(&enabledRetrievalMethodUrisParam)); if(keyInfoCtx->retrievalMethodCtx.enabledUris == xmlSecTransformUriTypeNone) { fprintf(stderr, "Error: failed to parse \"%s\"\n", xmlSecAppCmdLineParamGetStringList(&enabledRetrievalMethodUrisParam)); return(-1); } } /* read enabled KeyInfoReference uris */ if(xmlSecAppCmdLineParamGetStringList(&enabledKeyInfoReferenceUrisParam) != NULL) { keyInfoCtx->keyInfoReferenceCtx.enabledUris = xmlSecAppGetUriType( xmlSecAppCmdLineParamGetStringList(&enabledKeyInfoReferenceUrisParam)); if(keyInfoCtx->keyInfoReferenceCtx.enabledUris == xmlSecTransformUriTypeNone) { fprintf(stderr, "Error: failed to parse \"%s\"\n", xmlSecAppCmdLineParamGetStringList(&enabledKeyInfoReferenceUrisParam)); return(-1); } } return(0); } static int xmlSecAppLoadKeys(void) { xmlSecAppCmdLineValuePtr value; xmlSecKeyInfoCtxPtr keyInfoCtx; int verifyKeys = 0; int ret; if(g_keysManager != NULL) { fprintf(stderr, "Error: keys manager already initialized.\n"); return(-1); } /* create and initialize keys manager */ g_keysManager = xmlSecKeysMngrCreate(); if(g_keysManager == NULL) { fprintf(stderr, "Error: failed to create keys manager.\n"); return(-1); } if(xmlSecAppCryptoSimpleKeysMngrInit(g_keysManager) < 0) { fprintf(stderr, "Error: failed to initialize keys manager.\n"); return(-1); } /* create and initialize key info ctx */ keyInfoCtx = xmlSecKeyInfoCtxCreate(g_keysManager); if(keyInfoCtx == NULL) { fprintf(stderr, "Error: failed to initialize key info ctx.\n"); return(-1); } ret = xmlSecAppPrepareKeyInfoCtx(keyInfoCtx); if(ret < 0) { fprintf(stderr, "Error: failed to read key info ctx params.\n"); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } /* do we need to verify public/private keys? */ if(xmlSecAppCmdLineParamIsSet(&verifyKeysParam)) { verifyKeys = 1; } /* generate new keys */ for(value = genKeyParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", genKeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyGenerate(g_keysManager, value->strValue, value->paramNameValue) < 0) { fprintf(stderr, "Error: failed to generate key \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } /****************************************************************************************** * * FIRST, READ ALL CERTIFICATES * ******************************************************************************************/ #ifndef XMLSEC_NO_X509 /* read all trusted certs */ for(value = trustedParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", trustedParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrCertLoad(g_keysManager, value->strValue, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) { fprintf(stderr, "Error: failed to load trusted cert from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = trustedDerParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", trustedDerParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrCertLoad(g_keysManager, value->strValue, xmlSecKeyDataFormatDer, xmlSecKeyDataTypeTrusted) < 0) { fprintf(stderr, "Error: failed to load trusted cert from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } /* read all untrusted certs */ for(value = untrustedParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", untrustedParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrCertLoad(g_keysManager, value->strValue, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeNone) < 0) { fprintf(stderr, "Error: failed to load untrusted cert from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = untrustedDerParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", untrustedDerParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrCertLoad(g_keysManager, value->strValue, xmlSecKeyDataFormatDer, xmlSecKeyDataTypeNone) < 0) { fprintf(stderr, "Error: failed to load untrusted cert from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } /* read all crls*/ for(value = crlPemParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", crlPemParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrCrlLoad(g_keysManager, value->strValue, xmlSecKeyDataFormatPem) < 0) { fprintf(stderr, "Error: failed to load CRLs from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = crlDerParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", crlDerParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrCrlLoad(g_keysManager, value->strValue, xmlSecKeyDataFormatDer) < 0) { fprintf(stderr, "Error: failed to load CRLs from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_X509 */ /****************************************************************************************** * * XMLSEC KEY FILE * ******************************************************************************************/ for(value = keysFileParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", keysFileParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrLoad(g_keysManager, value->strValue) < 0) { fprintf(stderr, "Error: failed to load xml keys file \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } /****************************************************************************************** * * PRIVATE KEYS * ******************************************************************************************/ for(value = privkeyParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", privkeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatPem, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load private key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = privkeyDerParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", privkeyDerParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatDer, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load private key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = pkcs8PemParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pkcs8PemParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatPkcs8Pem, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load private key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = pkcs8DerParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pkcs8DerParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatPkcs8Der, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load private key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #ifndef XMLSEC_NO_X509 /* read all pkcs12 files */ if(xmlSecAppCmdLineParamIsSet(&pkcs12PersistParam)) { xmlSecImportSetPersistKey(); } for(value = pkcs12Param.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pkcs12Param.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrPkcs12KeyLoad(g_keysManager, value->strValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load pkcs12 key from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_X509 */ for(value = privkeyOpensslStoreParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", privkeyOpensslStoreParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatStore, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load private key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = privkeyOpensslEngineParam.value; value != NULL; value = value->next) { /* we expect at least one parameter for the key's engine+id */ if(value->strListValue == NULL || value->strListValue[0] == '\0') { fprintf(stderr, "Error: invalid value for option \"%s\".\n", privkeyOpensslEngineParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } /* the params format is: <openssl-engine>;<openssl-key-id>[,<crtfile>[,<crtfile>[...]]] */ if(xmlSecAppCryptoSimpleKeysMngrEngineKeyAndCertsLoad(g_keysManager, value->strListValue, value->strListValue + strlen(value->strListValue) + 1, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatEngine, xmlSecKeyDataFormatPem, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load private key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } /****************************************************************************************** * * PUBLIC KEYS * ******************************************************************************************/ for(value = pubkeyParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pubkeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic, xmlSecKeyDataFormatPem, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load public key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = pubkeyDerParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pubkeyDerParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic, xmlSecKeyDataFormatDer, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load public key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = pubkeyOpensslStoreParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pubkeyOpensslStoreParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic, xmlSecKeyDataFormatStore, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load public key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = pubkeyOpensslEngineParam.value; value != NULL; value = value->next) { /* we expect at least one parameter for the key's engine+id */ if(value->strListValue == NULL || value->strListValue[0] == '\0') { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pubkeyOpensslEngineParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } /* the params format is: <openssl-engine>;<openssl-key-id>[,<crtfile>[,<crtfile>[...]]] */ if(xmlSecAppCryptoSimpleKeysMngrEngineKeyAndCertsLoad(g_keysManager, value->strListValue, value->strListValue + strlen(value->strListValue) + 1, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatEngine, xmlSecKeyDataFormatPem, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load private key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #ifndef XMLSEC_NO_X509 /* read all public keys in certs */ for(value = pubkeyCertParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pubkeyCertParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic, xmlSecKeyDataFormatCertPem, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load public key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } for(value = pubkeyCertDerParam.value; value != NULL; value = value->next) { if(value->strListValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", pubkeyCertDerParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrKeyAndCertsLoad(g_keysManager, value->strListValue, xmlSecAppCmdLineParamGetString(&pwdParam), value->paramNameValue, xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic, xmlSecKeyDataFormatCertDer, keyInfoCtx, verifyKeys) < 0) { fprintf(stderr, "Error: failed to load public key from \"%s\".\n", value->strListValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_X509 */ /****************************************************************************************** * * SYMMETRICAL KEYS * ******************************************************************************************/ #ifndef XMLSEC_NO_AES /* read all AES keys */ for(value = aesKeyParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", aesKeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrBinaryKeyLoad(g_keysManager, (const char*)xmlSecNameAESKeyValue, value->strValue, value->paramNameValue) < 0) { fprintf(stderr, "Error: failed to load aes key from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_AES */ #ifndef XMLSEC_NO_CONCATKDF /* read all ConcatKDF keys */ for(value = concatKdfKeyParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", hmacKeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrBinaryKeyLoad(g_keysManager, (const char*)xmlSecNameConcatKdfKeyValue, value->strValue, value->paramNameValue) < 0) { fprintf(stderr, "Error: failed to load ConcatKDF key from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_CONCATKDF */ #ifndef XMLSEC_NO_DES /* read all des keys */ for(value = desKeyParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", desKeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrBinaryKeyLoad(g_keysManager, (const char*)xmlSecNameDESKeyValue, value->strValue, value->paramNameValue) < 0) { fprintf(stderr, "Error: failed to load des key from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_DES */ #ifndef XMLSEC_NO_HMAC /* read all hmac keys */ for(value = hmacKeyParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", hmacKeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrBinaryKeyLoad(g_keysManager, (const char*)xmlSecNameHMACKeyValue, value->strValue, value->paramNameValue) < 0) { fprintf(stderr, "Error: failed to load hmac key from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_HMAC */ #ifndef XMLSEC_NO_PBKDF2 /* read all Pbkdf2 keys */ for(value = pbkdf2KeyParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", hmacKeyParam.fullName); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } else if(xmlSecAppCryptoSimpleKeysMngrBinaryKeyLoad(g_keysManager, (const char*)xmlSecNamePbkdf2KeyValue, value->strValue, value->paramNameValue) < 0) { fprintf(stderr, "Error: failed to load Pbkdf2 key from \"%s\".\n", value->strValue); xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(-1); } } #endif /* XMLSEC_NO_PBKDF2 */ /* DONE */ xmlSecKeyInfoCtxDestroy(keyInfoCtx); return(0); } /** * Callbacks for supporting mapping URLs to files */ static int xmlSecAppInputMatchCallback(char const* filename) { xmlSecAppCmdLineValuePtr value; if(filename == NULL) { return(0); } for(value = urlMapParam.value; value != NULL; value = value->next) { if((value->strValue == NULL) || (value->paramNameValue == NULL)) { continue; } if(strcmp(filename, value->paramNameValue) == 0) { if(g_printVerboseDebug != 0) { fprintf(stderr, "Debug: found mapped file \"%s\" for url \"%s\"\n", value->strValue, filename); } return(1); } } if(g_blockNetworkIO != 0) { static const xmlChar http[] = "http://"; static const xmlChar https[] = "https://"; static const xmlChar ftp[] = "ftp://"; if(xmlStrncasecmp(BAD_CAST filename, http, xmlStrlen(http)) == 0) { if(g_printVerboseDebug != 0) { fprintf(stderr, "Debug: blocking access to \"%s\"\n", filename); } return(1); } if(xmlStrncasecmp(BAD_CAST filename, https, xmlStrlen(https)) == 0) { if(g_printVerboseDebug != 0) { fprintf(stderr, "Debug: blocking access to \"%s\"\n", filename); } return(1); } if(xmlStrncasecmp(BAD_CAST filename, ftp, xmlStrlen(ftp)) == 0) { if(g_printVerboseDebug != 0) { fprintf(stderr, "Debug: blocking access to \"%s\"\n", filename); } return(1); } } return(0); } static void* xmlSecAppInputOpenCallback(char const* filename) { xmlSecAppCmdLineValuePtr value; if(filename == NULL) { return(NULL); } for(value = urlMapParam.value; value != NULL; value = value->next) { if((value->strValue == NULL) || (value->paramNameValue == NULL)) { continue; } if(strcmp(filename, value->paramNameValue) == 0) { FILE * f = NULL; #if defined(_MSC_VER) fopen_s(&f, value->strValue, "rb"); #else /* defined(_MSC_VER) */ f = fopen(value->strValue, "rb"); #endif /* defined(_MSC_VER) */ if(f == NULL) { fprintf(stdout, "Error: can not open file \"%s\" for url \"%s\"\n", value->strValue, filename); return(NULL); } if(g_printVerboseDebug != 0) { fprintf(stdout, "Debug: opened file \"%s\" for url \"%s\"\n", value->strValue, filename); } return(f); } } return(NULL); } static int xmlSecAppInputReadCallback(void* context, char* buffer, int len) { FILE* f = (FILE*)context; size_t res; if((f == NULL) || (len < 0)) { return(-1); } if(feof(f)) { return(0); } res = fread(buffer, 1, (size_t)len, f); if(ferror(f)) { return(-1); } return((int)res); } static int xmlSecAppInputCloseCallback(void* context) { FILE* f = (FILE*)context; int ret; if(f == NULL) { return(-1); } ret = fclose(f); if(ret != 0) { return(-1); } if(g_printVerboseDebug != 0) { fprintf(stdout, "Debug: closed file\n"); } return(0); } static int intialized = 0; #ifndef XMLSEC_NO_XSLT static xsltSecurityPrefsPtr xsltSecPrefs = NULL; #endif /* XMLSEC_NO_XSLT */ static int xmlSecAppInit(void) { int ret; if(intialized != 0) { return(0); } intialized = 1; /* Init libxml */ xmlInitParser(); LIBXML_TEST_VERSION /* Init libxslt */ #ifndef XMLSEC_NO_XSLT /* disable everything */ xsltSecPrefs = xsltNewSecurityPrefs(); xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid); xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid); xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid); xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid); xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid); xsltSetDefaultSecurityPrefs(xsltSecPrefs); #endif /* XMLSEC_NO_XSLT */ /* Init xmlsec */ ret = xmlSecInit(); if(ret < 0) { fprintf(stderr, "Error: xmlsec intialization failed.\n"); return(-1); } if(xmlSecCheckVersion() != 1) { fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n"); return(-1); } /* Setup IO callbacks */ ret = xmlSecIORegisterCallbacks(xmlSecAppInputMatchCallback, xmlSecAppInputOpenCallback, xmlSecAppInputReadCallback, xmlSecAppInputCloseCallback); if(ret < 0) { fprintf(stderr, "Error: xmlsec IO callbacks intialization failed.\n"); return(-1); } #if !defined(XMLSEC_NO_CRYPTO_DYNAMIC_LOADING) && defined(XMLSEC_CRYPTO_DYNAMIC_LOADING) if(xmlSecCryptoDLLoadLibrary(BAD_CAST g_xmlSecCryptoLibrary) < 0) { fprintf(stderr, "Error: unable to load xmlsec-%s library. Make sure that you have\n" "this it installed, check shared libraries path (LD_LIBRARY_PATH)\n" "environment variable or use \"--crypto\" option to specify different\n" "crypto engine.\n", ((g_xmlSecCryptoLibrary != NULL) ? BAD_CAST g_xmlSecCryptoLibrary : xmlSecGetDefaultCrypto()) ); return(-1); } #endif /* !defined(XMLSEC_NO_CRYPTO_DYNAMIC_LOADING) && defined(XMLSEC_CRYPTO_DYNAMIC_LOADING) */ /* Init Crypto */ if(xmlSecAppCryptoInit(xmlSecAppCmdLineParamGetString(&cryptoConfigParam)) < 0) { fprintf(stderr, "Error: xmlsec crypto intialization failed.\n"); return(-1); } return(0); } static void xmlSecAppShutdown(void) { if(intialized == 0) { return; } /* Shutdown Crypto */ if(xmlSecAppCryptoShutdown() < 0) { fprintf(stderr, "Error: xmlsec crypto shutdown failed.\n"); } /* Shutdown xmlsec */ if(xmlSecShutdown() < 0) { fprintf(stderr, "Error: xmlsec shutdown failed.\n"); } /* Shutdown libxslt/libxml */ #ifndef XMLSEC_NO_XSLT xsltFreeSecurityPrefs(xsltSecPrefs); xsltCleanupGlobals(); #endif /* XMLSEC_NO_XSLT */ xmlCleanupParser(); } static xmlSecAppXmlDataPtr xmlSecAppXmlDataCreate(const char* filename, const xmlChar* defStartNodeName, const xmlChar* defStartNodeNs) { xmlSecAppCmdLineValuePtr value; xmlSecAppXmlDataPtr data; xmlNodePtr cur = NULL; xmlChar* attrName; xmlChar* nodeName; xmlChar* nsHref; xmlChar* buf; if(filename == NULL) { fprintf(stderr, "Error: xml filename is null\n"); return(NULL); } /* create object */ data = (xmlSecAppXmlDataPtr) xmlMalloc(sizeof(xmlSecAppXmlData)); if(data == NULL) { fprintf(stderr, "Error: failed to create xml data\n"); return(NULL); } memset(data, 0, sizeof(xmlSecAppXmlData)); /* parse doc */ data->doc = xmlSecParseFile(filename); if(data->doc == NULL) { fprintf(stderr, "Error: failed to parse xml file \"%s\"\n", filename); xmlSecAppXmlDataDestroy(data); return(NULL); } /* load dtd and set default attrs and ids */ if(xmlSecAppCmdLineParamGetString(&dtdFileParam) != NULL) { xmlValidCtxt ctx; data->dtd = xmlParseDTD(NULL, BAD_CAST xmlSecAppCmdLineParamGetString(&dtdFileParam)); if(data->dtd == NULL) { fprintf(stderr, "Error: failed to parse dtd file \"%s\"\n", xmlSecAppCmdLineParamGetString(&dtdFileParam)); xmlSecAppXmlDataDestroy(data); return(NULL); } memset(&ctx, 0, sizeof(ctx)); /* we don't care is doc actually valid or not */ xmlValidateDtd(&ctx, data->doc, data->dtd); } /* set ID attributes from command line */ for(value = idAttrParam.value; value != NULL; value = value->next) { if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", idAttrParam.fullName); xmlSecAppXmlDataDestroy(data); return(NULL); } attrName = (value->paramNameValue != NULL) ? BAD_CAST value->paramNameValue : BAD_CAST "id"; buf = xmlStrdup(BAD_CAST value->strValue); if(buf == NULL) { fprintf(stderr, "Error: failed to duplicate string \"%s\"\n", value->strValue); xmlSecAppXmlDataDestroy(data); return(NULL); } nodeName = (xmlChar*)strrchr((char*)buf, ':'); if(nodeName != NULL) { (*(nodeName++)) = '\0'; nsHref = buf; } else { nodeName = buf; nsHref = NULL; } /* process children first because it does not matter much but does simplify code */ cur = xmlSecGetNextElementNode(data->doc->children); while(cur != NULL) { if(xmlSecAppAddIDAttr(cur, attrName, nodeName, nsHref) < 0) { fprintf(stderr, "Error: failed to add ID attribute \"%s\" for node \"%s\"\n", attrName, value->strValue); xmlFree(buf); xmlSecAppXmlDataDestroy(data); return(NULL); } cur = xmlSecGetNextElementNode(cur->next); } xmlFree(buf); } /* add ID attributes from command line */ for(value = addIdAttrParam.value; value != NULL; value = value->next) { const xmlChar* idAttr[] = { NULL, NULL }; if(value->strValue == NULL) { fprintf(stderr, "Error: invalid value for option \"%s\".\n", idAttrParam.fullName); xmlSecAppXmlDataDestroy(data); return(NULL); } idAttr[0] = BAD_CAST value->strValue; xmlSecAddIDs(data->doc, NULL, idAttr); } /* now find the start node */ if(xmlSecAppCmdLineParamGetString(&nodeIdParam) != NULL) { xmlAttrPtr attr; attr = xmlGetID(data->doc, BAD_CAST xmlSecAppCmdLineParamGetString(&nodeIdParam)); if(attr == NULL) { fprintf(stderr, "Error: failed to find node with id=\"%s\"\n", xmlSecAppCmdLineParamGetString(&nodeIdParam)); xmlSecAppXmlDataDestroy(data); return(NULL); } cur = attr->parent; } else if(xmlSecAppCmdLineParamGetString(&nodeNameParam) != NULL) { xmlChar* name; xmlChar* ns; buf = xmlStrdup(BAD_CAST xmlSecAppCmdLineParamGetString(&nodeNameParam)); if(buf == NULL) { fprintf(stderr, "Error: failed to duplicate node \"%s\"\n", xmlSecAppCmdLineParamGetString(&nodeNameParam)); xmlSecAppXmlDataDestroy(data); return(NULL); } name = (xmlChar*)strrchr((char*)buf, ':'); if(name != NULL) { (*(name++)) = '\0'; ns = buf; } else { name = buf; ns = NULL; } cur = xmlSecFindNode(xmlDocGetRootElement(data->doc), name, ns); if(cur == NULL) { fprintf(stderr, "Error: failed to find node with name=\"%s\"\n", name); xmlFree(buf); xmlSecAppXmlDataDestroy(data); return(NULL); } xmlFree(buf); } else if(xmlSecAppCmdLineParamGetString(&nodeXPathParam) != NULL) { xmlXPathContextPtr ctx = NULL; xmlXPathObjectPtr obj = NULL; xmlNodePtr rootNode; xmlNsPtr ns; int ret; rootNode = xmlDocGetRootElement(data->doc); if(rootNode == NULL) { fprintf(stderr, "Error: failed to find root node\n"); xmlSecAppXmlDataDestroy(data); return(NULL); } ctx = xmlXPathNewContext(data->doc); if(ctx == NULL) { fprintf(stderr, "Error: failed to create xpath context\n"); xmlSecAppXmlDataDestroy(data); return(NULL); } /* register namespaces from the root node */ for(ns = rootNode->nsDef; ns != NULL; ns = ns->next) { if(ns->prefix != NULL){ ret = xmlXPathRegisterNs(ctx, ns->prefix, ns->href); if(ret != 0) { fprintf(stderr, "Error: failed to register namespace \"%s\"\n", ns->prefix); xmlXPathFreeContext(ctx); xmlSecAppXmlDataDestroy(data); return(NULL); } } } obj = xmlXPathEval(BAD_CAST xmlSecAppCmdLineParamGetString(&nodeXPathParam), ctx); if(obj == NULL) { fprintf(stderr, "Error: failed to evaluate xpath expression\n"); xmlXPathFreeContext(ctx); xmlSecAppXmlDataDestroy(data); return(NULL); } if((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) { fprintf(stderr, "Error: xpath expression evaluation does not return a single node as expected\n"); xmlXPathFreeObject(obj); xmlXPathFreeContext(ctx); xmlSecAppXmlDataDestroy(data); return(NULL); } cur = obj->nodesetval->nodeTab[0]; xmlXPathFreeContext(ctx); xmlXPathFreeObject(obj); } else { cur = xmlDocGetRootElement(data->doc); if(cur == NULL) { fprintf(stderr, "Error: failed to get root element\n"); xmlSecAppXmlDataDestroy(data); return(NULL); } } if(defStartNodeName != NULL) { data->startNode = xmlSecFindNode(cur, defStartNodeName, defStartNodeNs); if(data->startNode == NULL) { fprintf(stderr, "Error: failed to find default node with name=\"%s\"\n", defStartNodeName); xmlSecAppXmlDataDestroy(data); return(NULL); } } else { data->startNode = cur; } return(data); } static void xmlSecAppXmlDataDestroy(xmlSecAppXmlDataPtr data) { if(data == NULL) { fprintf(stderr, "Error: xml data is null\n"); return; } if(data->dtd != NULL) { xmlFreeDtd(data->dtd); } if(data->doc != NULL) { xmlFreeDoc(data->doc); } memset(data, 0, sizeof(xmlSecAppXmlData)); xmlFree(data); } static xmlSecAppCommand xmlSecAppParseCommand(const char* cmd, xmlSecAppCmdLineParamTopic* cmdLineTopics, xmlSecAppCommand* subCommand) { if(subCommand != NULL) { (*subCommand) = xmlSecAppCommandUnknown; } if((cmd == NULL) || (cmdLineTopics == NULL)) { return(xmlSecAppCommandUnknown); } else if((strcmp(cmd, "help") == 0) || (strcmp(cmd, "--help") == 0)) { (*cmdLineTopics) = 0; return(xmlSecAppCommandHelp); } else if((strcmp(cmd, "help-all") == 0) || (strcmp(cmd, "--help-all") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicAll; return(xmlSecAppCommandHelp); } else if((strncmp(cmd, "help-", 5) == 0) || (strncmp(cmd, "--help-", 7) == 0)) { cmd = (cmd[0] == '-') ? cmd + 7 : cmd + 5; if(subCommand) { (*subCommand) = xmlSecAppParseCommand(cmd, cmdLineTopics, NULL); } else { (*cmdLineTopics) = 0; } return(xmlSecAppCommandHelp); } else if((strcmp(cmd, "version") == 0) || (strcmp(cmd, "--version") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicVersion; return(xmlSecAppCommandVersion); } else if((strcmp(cmd, "list-key-data") == 0) || (strcmp(cmd, "--list-key-data") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig; return(xmlSecAppCommandListKeyData); } else if((strcmp(cmd, "check-key-data") == 0) || (strcmp(cmd, "--check-key-data") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig; return(xmlSecAppCommandCheckKeyData); } else if((strcmp(cmd, "list-transforms") == 0) || (strcmp(cmd, "--list-transforms") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig; return(xmlSecAppCommandListTransforms); } else if((strcmp(cmd, "check-transforms") == 0) || (strcmp(cmd, "--check-transforms") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig; return(xmlSecAppCommandCheckTransforms); } else if((strcmp(cmd, "keys") == 0) || (strcmp(cmd, "--keys") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig | xmlSecAppCmdLineTopicKeysMngr | xmlSecAppCmdLineTopicX509Certs; return(xmlSecAppCommandKeys); } else #ifndef XMLSEC_NO_XMLDSIG if((strcmp(cmd, "sign") == 0) || (strcmp(cmd, "--sign") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig | xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicDSigSign | xmlSecAppCmdLineTopicKeysMngr | xmlSecAppCmdLineTopicX509Certs; return(xmlSecAppCommandSign); } else if((strcmp(cmd, "verify") == 0) || (strcmp(cmd, "--verify") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig | xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicDSigVerify | xmlSecAppCmdLineTopicKeysMngr | xmlSecAppCmdLineTopicX509Certs; return(xmlSecAppCommandVerify); } else #ifndef XMLSEC_NO_TMPL_TEST if((strcmp(cmd, "sign-tmpl") == 0) || (strcmp(cmd, "--sign-tmpl") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig | xmlSecAppCmdLineTopicDSigCommon | xmlSecAppCmdLineTopicDSigSign | xmlSecAppCmdLineTopicKeysMngr | xmlSecAppCmdLineTopicX509Certs; return(xmlSecAppCommandSignTmpl); } else #endif /* XMLSEC_NO_TMPL_TEST */ #endif /* XMLSEC_NO_XMLDSIG */ #ifndef XMLSEC_NO_XMLENC if((strcmp(cmd, "encrypt") == 0) || (strcmp(cmd, "--encrypt") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig | xmlSecAppCmdLineTopicEncCommon | xmlSecAppCmdLineTopicEncEncrypt | xmlSecAppCmdLineTopicKeysMngr | xmlSecAppCmdLineTopicX509Certs; return(xmlSecAppCommandEncrypt); } else if((strcmp(cmd, "decrypt") == 0) || (strcmp(cmd, "--decrypt") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig | xmlSecAppCmdLineTopicEncCommon | xmlSecAppCmdLineTopicEncDecrypt | xmlSecAppCmdLineTopicKeysMngr | xmlSecAppCmdLineTopicX509Certs; return(xmlSecAppCommandDecrypt); } else #ifndef XMLSEC_NO_TMPL_TEST if((strcmp(cmd, "encrypt-tmpl") == 0) || (strcmp(cmd, "--encrypt-tmpl") == 0)) { (*cmdLineTopics) = xmlSecAppCmdLineTopicGeneral | xmlSecAppCmdLineTopicCryptoConfig | xmlSecAppCmdLineTopicEncCommon | xmlSecAppCmdLineTopicEncEncrypt | xmlSecAppCmdLineTopicKeysMngr | xmlSecAppCmdLineTopicX509Certs; return(xmlSecAppCommandEncryptTmpl); } else #endif /* XMLSEC_NO_TMPL_TEST */ #endif /* XMLSEC_NO_XMLENC */ if(1) { (*cmdLineTopics) = 0; return(xmlSecAppCommandUnknown); } } static void xmlSecAppPrintHelp(xmlSecAppCommand command, xmlSecAppCmdLineParamTopic topics) { switch(command) { case xmlSecAppCommandUnknown: fprintf(stderr, "Unknown command\n"); fprintf(stdout, "%s%s\n", helpCommands1, helpCommands2); break; case xmlSecAppCommandHelp: fprintf(stdout, "%s%s\n", helpCommands1, helpCommands2); break; case xmlSecAppCommandVersion: fprintf(stdout, "%s\n", helpVersion); break; case xmlSecAppCommandListKeyData: fprintf(stdout, "%s\n", helpListKeyData); break; case xmlSecAppCommandCheckKeyData: fprintf(stdout, "%s\n", helpCheckKeyData); break; case xmlSecAppCommandListTransforms: fprintf(stdout, "%s\n", helpListTransforms); break; case xmlSecAppCommandCheckTransforms: fprintf(stdout, "%s\n", helpCheckTransforms); break; case xmlSecAppCommandKeys: fprintf(stdout, "%s\n", helpKeys); break; case xmlSecAppCommandSign: fprintf(stdout, "%s\n", helpSign); break; case xmlSecAppCommandVerify: fprintf(stdout, "%s\n", helpVerify); break; case xmlSecAppCommandEncrypt: fprintf(stdout, "%s\n", helpEncrypt); break; case xmlSecAppCommandDecrypt: fprintf(stdout, "%s\n", helpDecrypt); break; case xmlSecAppCommandSignTmpl: fprintf(stdout, "%s\n", helpSignTmpl); break; case xmlSecAppCommandEncryptTmpl: fprintf(stdout, "%s\n", helpEncryptTmpl); break; } if(topics != 0) { fprintf(stdout, "Options:\n"); xmlSecAppCmdLineParamsListPrint(parameters, topics, stdout); fprintf(stdout, "\n"); } fprintf(stdout, "\n%s\n", bugs); fprintf(stdout, "%s\n", copyright); } static xmlSecTransformUriType xmlSecAppGetUriType(const char* string) { xmlSecTransformUriType type = xmlSecTransformUriTypeNone; while((string != NULL) && (string[0] != '\0')) { if(strcmp(string, "empty") == 0) { type |= xmlSecTransformUriTypeEmpty; } else if(strcmp(string, "same-doc") == 0) { type |= xmlSecTransformUriTypeSameDocument; } else if(strcmp(string, "local") == 0) { type |= xmlSecTransformUriTypeLocal; } else if(strcmp(string, "remote") == 0) { type |= xmlSecTransformUriTypeRemote; } else { fprintf(stderr, "Error: invalid uri type: \"%s\"\n", string); return(xmlSecTransformUriTypeNone); } string += strlen(string) + 1; } return(type); } static xmlOutputBufferPtr xmlSecAppOpenFile(const char* filename, const char* encoding) { xmlOutputBufferPtr outBuffer = NULL; xmlCharEncodingHandlerPtr encoder = NULL; if(encoding != NULL) { encoder = xmlFindCharEncodingHandler(encoding); if(encoder == NULL) { return(NULL); } } if((filename == NULL) || (strcmp(filename, XMLSEC_STDOUT_FILENAME) == 0)) { outBuffer = xmlOutputBufferCreateFile(stdout, encoder); if (outBuffer == NULL) { fprintf(stderr, "Error: failed to create output buffer for stdout\n"); return(NULL); } } else { outBuffer = xmlOutputBufferCreateFilename(filename, encoder, 0); if (outBuffer == NULL) { fprintf(stderr, "Error: failed to open file \"%s\"\n", filename); return(NULL); } } return(outBuffer); } #define XMLSEC_OUTPUT_TMPL_PARAM "{inputfile}" static char* xmlSecAppGetOutputFilename(const char* inputFileName, const char* outputFileNameTmpl) { char* inputFileNameCopy = NULL; char* inputBasename; char* outputFileNameTmplPointer; size_t resSize; char* res = NULL; #if !defined(_MSC_VER) const char* tmp = NULL; char* tmp2; #else /* !defined(_MSC_VER) */ errno_t err; #endif /* !defined(_MSC_VER) */ if((inputFileName == NULL) || (outputFileNameTmpl == NULL)) { return(NULL); } /* is there something to replace? */ outputFileNameTmplPointer = strstr(outputFileNameTmpl, XMLSEC_OUTPUT_TMPL_PARAM); if(outputFileNameTmplPointer == NULL) { return((char*)xmlStrdup(BAD_CAST outputFileNameTmpl)); } /* get input file */ inputFileNameCopy = (char*)xmlStrdup(BAD_CAST inputFileName); if (inputFileNameCopy == NULL) { fprintf(stderr, "Error: failed to duplicate input filename \"%s\"\n", inputFileName); goto done; } #if !defined(_MSC_VER) inputBasename = basename(inputFileNameCopy); if(inputBasename == NULL) { fprintf(stderr, "Error: failed to get basename for input filename \"%s\"\n", inputFileName); goto done; } tmp2 = strrchr(inputBasename, '.'); if(tmp2 != NULL) { // remove extension if any (*tmp2) = '\0'; } #else /* !defined(_MSC_VER) */ inputBasename = inputFileNameCopy; err = _splitpath_s(inputFileName, NULL, 0, NULL, 0, inputBasename, strlen(inputBasename), NULL, 0); if(err != 0) { fprintf(stderr, "Error: failed to split the input filename \"%s\": %d\n", inputFileName, (int)err); goto done; } #endif /* !defined(_MSC_VER) */ /* create output filename */ resSize = strlen(outputFileNameTmpl) + strlen(inputBasename) + 1; res = (char*)xmlMalloc(resSize); if(res == NULL) { fprintf(stderr, "Error: cannot allocate %d bytes for the output filename\n", (int)resSize); goto done; } memset(res, 0, resSize); /* prefix */ if ((outputFileNameTmplPointer - outputFileNameTmpl) > 0) { memcpy(res, outputFileNameTmpl, (size_t)(outputFileNameTmplPointer - outputFileNameTmpl)); } outputFileNameTmplPointer += strlen(XMLSEC_OUTPUT_TMPL_PARAM); /* input filename */ #if !defined(_MSC_VER) tmp = strcat(res, inputBasename); if(tmp == NULL) { fprintf(stderr, "Error: failed to append input basemame\n"); goto done; } #else /* !defined(_MSC_VER) */ err = strcat_s(res, resSize, inputBasename); if(err != 0) { fprintf(stderr, "Error: failed to append input basemame: %d\n", (int)err); goto done; } #endif /* !defined(_MSC_VER) */ /* suffix */ #if !defined(_MSC_VER) tmp = strcat(res, outputFileNameTmplPointer); if(tmp == NULL) { fprintf(stderr, "Error: failed to append output template suffix\n"); goto done; } #else /* !defined(_MSC_VER) */ err = strcat_s(res, resSize, outputFileNameTmplPointer); if(err != 0) { fprintf(stderr, "Error: failed to append output template suffix: %d\n", (int)err); goto done; } #endif /* !defined(_MSC_VER) */ /* done */ done: if(inputFileNameCopy != NULL) { xmlFree(inputFileNameCopy); } return(res); } static int xmlSecAppWriteResult(const char* inputFileName, const char* outputFileNameTmpl, xmlDocPtr doc, xmlSecBufferPtr buffer, const xmlChar* encoding) { char* outputFileName = NULL; xmlOutputBufferPtr outBuffer; int ret; /* get output filename by replacing '{inputfile}' with input file name */ if((inputFileName != NULL) && (outputFileNameTmpl != NULL)) { outputFileName = xmlSecAppGetOutputFilename(inputFileName, outputFileNameTmpl); if(outputFileName == NULL) { fprintf(stderr, "Error: can't create output filename\n"); return(-1); } } /* open file */ outBuffer = xmlSecAppOpenFile(outputFileName != NULL ? outputFileName : outputFileNameTmpl, (const char *)encoding); if ((outputFileName != NULL) && (outputFileName != outputFileNameTmpl)) { xmlFree(outputFileName); } if(outBuffer == NULL) { return(-1); } /* dump output */ if(doc != NULL) { ret = xmlSaveFileTo(outBuffer, doc, (const char*)doc->encoding); if (ret < 0) { fprintf(stderr, "Error: failed to write xml output\n"); (void)xmlOutputBufferClose(outBuffer); return(-1); } /* xmlSaveFileTo closes the buffer */ } else if((buffer != NULL) && (xmlSecBufferGetData(buffer) != NULL)) { ret = xmlOutputBufferWrite(outBuffer, (int)xmlSecBufferGetSize(buffer), (const char*)xmlSecBufferGetData(buffer)); if (ret < 0) { fprintf(stderr, "Error: failed to write binary output\n"); (void)xmlOutputBufferClose(outBuffer); return(-1); } (void)xmlOutputBufferClose(outBuffer); } else { fprintf(stderr, "Error: both result doc and result buffer are null\n"); (void)xmlOutputBufferClose(outBuffer); return(-1); } /* done */ return(0); } static int xmlSecAppAddIDAttr(xmlNodePtr node, const xmlChar* attrName, const xmlChar* nodeName, const xmlChar* nsHref) { xmlAttrPtr attr, tmpAttr; xmlNodePtr cur; xmlChar* id; if((node == NULL) || (attrName == NULL) || (nodeName == NULL)) { return(-1); } /* process children first because it does not matter much but does simplify code */ cur = xmlSecGetNextElementNode(node->children); while(cur != NULL) { if(xmlSecAppAddIDAttr(cur, attrName, nodeName, nsHref) < 0) { return(-1); } cur = xmlSecGetNextElementNode(cur->next); } /* node name must match */ if(!xmlStrEqual(node->name, nodeName)) { return(0); } /* if nsHref is set then it also should match */ if((nsHref != NULL) && (node->ns != NULL) && (!xmlStrEqual(nsHref, node->ns->href))) { return(0); } /* the attribute with name equal to attrName should exist */ for(attr = node->properties; attr != NULL; attr = attr->next) { if(xmlStrEqual(attr->name, attrName)) { break; } } if(attr == NULL) { return(0); } /* and this attr should have a value */ id = xmlNodeListGetString(node->doc, attr->children, 1); if(id == NULL) { return(0); } /* check that we don't have same ID already */ tmpAttr = xmlGetID(node->doc, id); if(tmpAttr == NULL) { xmlAddID(NULL, node->doc, id, attr); } else if(tmpAttr != attr) { fprintf(stderr, "Error: duplicate ID attribute \"%s\"\n", id); xmlFree(id); return(-1); } xmlFree(id); return(0); }