in xsec/tools/checksig/checksig.cpp [171:569]
int evaluate(int argc, char ** argv) {
char * filename = NULL;
char * hmacKeyStr = NULL;
char * useIdAttributeNS = NULL;
char * useIdAttributeName = NULL;
XSECCryptoKey * key = NULL;
bool useXSECURIResolver = false;
bool useAnonymousResolver = false;
bool useInteropResolver = false;
#if defined (XSEC_HAVE_WINCAPI)
HCRYPTPROV win32CSP = 0;
#endif
bool skipRefs = false;
if (argc < 2) {
printUsage();
return 2;
}
// Run through parameters
int paramCount = 1;
while (paramCount < argc - 1) {
if (_stricmp(argv[paramCount], "--hmackey") == 0 || _stricmp(argv[paramCount], "-h") == 0) {
paramCount++;
hmacKeyStr = argv[paramCount++];
}
else if (_stricmp(argv[paramCount], "--skiprefs") == 0 || _stricmp(argv[paramCount], "-s") == 0) {
skipRefs = true;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--xsecresolver") == 0 || _stricmp(argv[paramCount], "-x") == 0) {
useXSECURIResolver = true;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--id") == 0) {
if (paramCount +1 >= argc) {
printUsage();
return 2;
}
paramCount++;
useIdAttributeName = argv[paramCount++];
}
else if (_stricmp(argv[paramCount], "--idns") == 0 || _stricmp(argv[paramCount], "-d") == 0) {
if (paramCount +2 >= argc) {
printUsage();
return 2;
}
paramCount++;
useIdAttributeNS = argv[paramCount++];
useIdAttributeName = argv[paramCount++];
}
#if defined (XSEC_HAVE_OPENSSL)
else if (_stricmp(argv[paramCount], "--interop") == 0 || _stricmp(argv[paramCount], "-i") == 0) {
// Use the interop key resolver
useInteropResolver = true;
paramCount++;
}
#endif
else if (_stricmp(argv[paramCount], "--anonymousresolver") == 0 || _stricmp(argv[paramCount], "-a") ==0) {
useAnonymousResolver = true;
paramCount++;
}
#if defined (XSEC_HAVE_WINCAPI)
else if (_stricmp(argv[paramCount], "--wincapi") == 0 || _stricmp(argv[paramCount], "-w") == 0 ||
_stricmp(argv[paramCount], "--winhmackey") == 0 || _stricmp(argv[paramCount], "-wh") == 0) {
WinCAPICryptoProvider * cp = new WinCAPICryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
if (_stricmp(argv[paramCount], "--winhmackey") == 0 || _stricmp(argv[paramCount], "-wh") == 0) {
// Create a SHA-1 based key based on the <string> parameter
paramCount++;
if (!CryptAcquireContext(&win32CSP,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
cerr << "Error obtaining default RSA_PROV" << endl;
return 2;
}
HCRYPTKEY k;
HCRYPTHASH h;
BOOL fResult = CryptCreateHash(
win32CSP,
CALG_SHA,
0,
0,
&h);
if (fResult == 0) {
cerr << "Error creating hash to create windows hmac key from password" << endl;
return 2;
}
fResult = CryptHashData(
h,
(unsigned char *) argv[paramCount],
(DWORD) strlen(argv[paramCount]),
0);
if (fResult == 0) {
cerr << "Error hashing password to create windows hmac key" << endl;
return 2;
}
// Now create a key
fResult = CryptDeriveKey(
win32CSP,
CALG_RC2,
h,
CRYPT_EXPORTABLE,
&k);
if (fResult == 0) {
cerr << "Error deriving key from hash value" << endl;
return 2;
}
// Wrap in a WinCAPI object
WinCAPICryptoKeyHMAC * hk;
hk = new WinCAPICryptoKeyHMAC(win32CSP);
hk->setWinKey(k);
key = hk;
CryptDestroyHash(h);
}
paramCount++;
}
#endif
else {
cerr << "Unknown option: " << argv[paramCount] << endl << endl;
printUsage();
return 2;
}
}
#if defined (XSEC_HAVE_WINCAPI) && !defined(XSEC_HAVE_OPENSSL)
// Use default DSS provider
WinCAPICryptoProvider * cp = new WinCAPICryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
#endif
if (paramCount >= argc) {
printUsage();
return 2;
}
filename = argv[paramCount];
// Create and set up the parser
XercesDOMParser * parser = new XercesDOMParser;
Janitor<XercesDOMParser> j_parser(parser);
parser->setDoNamespaces(true);
parser->setCreateEntityReferenceNodes(true);
// Now parse out file
bool errorsOccured = false;
XMLSize_t errorCount = 0;
try
{
parser->parse(filename);
errorCount = parser->getErrorCount();
if (errorCount > 0)
errorsOccured = true;
}
catch (const XMLException& e)
{
cerr << "An error occurred during parsing\n Message: "
<< e.getMessage() << endl;
errorsOccured = true;
}
catch (const DOMException& e)
{
cerr << "A DOM error occurred during parsing\n DOMException code: "
<< e.code << endl;
errorsOccured = true;
}
if (errorsOccured) {
cout << "Errors during parse" << endl;
return (2);
}
/*
Now that we have the parsed file, get the DOM document and start looking at it
*/
DOMNode *doc; // The document that we parsed
doc = parser->getDocument();
DOMDocument *theDOM = parser->getDocument();
// Find the signature node
DOMNode *sigNode = findDSIGNode(doc, "Signature");
// Create the signature checker
if (sigNode == 0) {
cerr << "Could not find <Signature> node in " << argv[argc-1] << endl;
return 2;
}
XSECProvider prov;
XSECKeyInfoResolverDefault theKeyInfoResolver;
DSIGSignature * sig = prov.newSignatureFromDOM(theDOM, sigNode);
// The only way we can verify is using keys read directly from the KeyInfo list,
// so we add a KeyInfoResolverDefault to the Signature.
sig->setKeyInfoResolver(&theKeyInfoResolver);
// Register defined attribute name
if (useIdAttributeName != NULL) {
sig->setIdByAttributeName(true);
if (useIdAttributeNS != NULL) {
sig->registerIdAttributeNameNS(MAKE_UNICODE_STRING(useIdAttributeNS),
MAKE_UNICODE_STRING(useIdAttributeName));
} else {
sig->registerIdAttributeName(MAKE_UNICODE_STRING(useIdAttributeName));
}
}
// Check whether we should use the internal resolver
if (useXSECURIResolver == true ||
useAnonymousResolver == true ||
useInteropResolver == true) {
AnonymousResolver theAnonymousResolver;
// Map out base path of the file
#if XSEC_HAVE_GETCWD_DYN
char *path = getcwd(NULL, 0);
char *baseURI = (char*)malloc(strlen(path) + 8 + 1 + strlen(filename) + 1);
#else
char path[PATH_MAX];
char baseURI[(PATH_MAX * 2) + 10];
getcwd(path, PATH_MAX);
#endif
strcpy(baseURI, "file:///");
// Ugly and nasty but quick
if (filename[0] != '\\' && filename[0] != '/' && filename[1] != ':') {
strcat(baseURI, path);
strcat(baseURI, "/");
} else if (path[1] == ':') {
path[2] = '\0';
strcat(baseURI, path);
}
strcat(baseURI, filename);
// Find any ':' and "\" characters
int lastSlash = 0;
for (unsigned int i = 8; i < strlen(baseURI); ++i) {
if (baseURI[i] == '\\') {
lastSlash = i;
baseURI[i] = '/';
}
else if (baseURI[i] == '/')
lastSlash = i;
}
// The last "\\" must prefix the filename
baseURI[lastSlash + 1] = '\0';
XMLCh * baseURIXMLCh = XMLString::transcode(baseURI);
XMLUri uri(MAKE_UNICODE_STRING(baseURI));
#if XSEC_HAVE_GETCWD_DYN
free(path);
free(baseURI);
#endif
if (useAnonymousResolver == true) {
sig->setURIResolver(&theAnonymousResolver);
}
sig->getURIResolver()->setBaseURI(baseURIXMLCh);
#if defined (XSEC_HAVE_OPENSSL)
if (useInteropResolver == true) {
InteropResolver ires(&(baseURIXMLCh[8]));
sig->setKeyInfoResolver(&ires);
}
#endif
XSEC_RELEASE_XMLCH(baseURIXMLCh);
}
bool result;
try {
// Load a key if necessary
if (hmacKeyStr != NULL) {
XSECCryptoKeyHMAC * hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC();
hmacKey->setKey((unsigned char *) hmacKeyStr, (unsigned int) strlen(hmacKeyStr));
sig->setSigningKey(hmacKey);
}
else if (key != NULL) {
sig->setSigningKey(key);
}
sig->load();
if (skipRefs)
result = sig->verifySignatureOnly();
else
result = sig->verify();
}
catch (const XSECException &e) {
char * msg = XMLString::transcode(e.getMsg());
cerr << "An error occurred during signature verification\n Message: "
<< msg << endl;
XSEC_RELEASE_XMLCH(msg);
errorsOccured = true;
return 2;
}
catch (const XSECCryptoException &e) {
cerr << "An error occurred during signature verification\n Message: "
<< e.getMsg() << endl;
errorsOccured = true;
#if defined (XSEC_HAVE_OPENSSL)
ERR_load_crypto_strings();
BIO * bio_err;
if ((bio_err=BIO_new(BIO_s_file())) != NULL)
BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
ERR_print_errors(bio_err);
#endif
return 2;
}
#if 0
catch (...) {
cerr << "Unknown Exception type occurred. Cleaning up and exiting\n" << endl;
return 2;
}
#endif
int retResult;
if (result) {
cout << "Signature verified OK!" << endl;
retResult = 0;
}
else {
cout << "Signature failed verification" << endl;
char * e = XMLString::transcode(sig->getErrMsgs());
cout << e << endl;
XSEC_RELEASE_XMLCH(e);
retResult = 1;
}
#if defined (XSEC_HAVE_WINCAPI)
// Clean up the handle to the CSP
if (win32CSP != 0)
CryptReleaseContext(win32CSP, 0);
#endif
// Janitor will clean up the parser
return retResult;
}