facho-signer: se separa main de libreria facho-signer
FossilOrigin-Name: ccb333de3a3210a4e82fb102e3eb41cb2d26c8fea5dd153898728978f85539b0
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| bin_PROGRAMS = facho_signer | ||||
| facho_signer_SOURCES = xades/xmlsec1/xmltree.c xades/xmlsec1/errors.c xades/templates.c xades/xades.c facho_signer.c | ||||
| facho_signer_SOURCES = xades/xmlsec1/xmltree.c xades/xmlsec1/errors.c xades/templates.c xades/xades.c facho_signer.c main.c | ||||
| facho_signer_CFLAGS = $(OPENSSL_CFLAGS) $(XMLSEC1_CFLAGS) -DXMLSEC_NOT_CRYPTO_DYNAMIC_LOADING | ||||
| facho_signer_LDADD = $(OPENSSL_LIBS) $(LIBLTDL) $(XMLSEC1_LIBS) | ||||
|   | ||||
| @@ -10,27 +10,24 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
|  | ||||
| #define print_error(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) | ||||
| #define print_info(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) | ||||
| #define xmlFachoPrintError(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) | ||||
| #define xmlFachoPrintInfo(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) | ||||
|  | ||||
| const xmlChar ublExtensionDSigNs[] = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"; | ||||
| const xmlChar policyIdDescription[] = "Política de firma para facturas electrónicas de la República de Colombia."; | ||||
| const xmlChar policyIdIdentifier[] = "https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf"; | ||||
|    | ||||
| char *basename = NULL; | ||||
|  | ||||
| // crea elemento /Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent | ||||
| xmlNodePtr | ||||
| static xmlNodePtr | ||||
| xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc); | ||||
|  | ||||
| // FeC requiere que el digest value del policy identifier sea | ||||
| // apartir del contenido de la url. | ||||
| int | ||||
| static int | ||||
| xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *, xmlSecBufferPtr); | ||||
|  | ||||
|  | ||||
| int | ||||
| static int | ||||
| xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { | ||||
|   xmlNodePtr qualifyingPropertiesNode = NULL; | ||||
|   xmlNodePtr signedPropertiesNode = NULL; | ||||
| @@ -47,13 +44,13 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { | ||||
|    | ||||
|   qualifyingPropertiesNode = xmlXadesTmplQualifyingPropertiesCreate(doc, signNode, BAD_CAST "xades-ref1"); | ||||
|   if (  qualifyingPropertiesNode == NULL ) { | ||||
|     print_error("error: failed to add QualifyingProperties node.\n"); | ||||
|     xmlFachoPrintError("error: failed to add QualifyingProperties node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signedPropertiesNode = xmlXadesTmplAddSignedProperties(qualifyingPropertiesNode, signedPropertiesId); | ||||
|   if ( signedPropertiesNode == NULL ) { | ||||
|     print_error("error: xades failed to add signed properties node.\n"); | ||||
|     xmlFachoPrintError("error: xades failed to add signed properties node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
| @@ -63,54 +60,54 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { | ||||
|                                             signedPropertiesRef, | ||||
|                                             BAD_CAST "http://uri.etsi.org/01903#SignedProperties"); | ||||
|   if ( refNode == NULL ) { | ||||
|     print_error("error: failed to add reference to signature template xades.\n"); | ||||
|     xmlFachoPrintError("error: failed to add reference to signature template xades.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|   if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformInclC14NId) == NULL ) { | ||||
|     print_error("error: failed to add enveloped transform to reference for xades\n"); | ||||
|     xmlFachoPrintError("error: failed to add enveloped transform to reference for xades\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   const time_t now = time(NULL); | ||||
|   signedSignaturePropertiesNode = xmlXadesTmplAddSignedSignatureProperties(signedPropertiesNode, localtime(&now)); | ||||
|   if ( signedSignaturePropertiesNode == NULL ) { | ||||
|     print_error("error: xades failed to add signed signature properties node.\n"); | ||||
|     xmlFachoPrintError("error: xades failed to add signed signature properties node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signingCertificateNode = xmlXadesTmplAddSigningCertificate(signedSignaturePropertiesNode, xmlSecTransformSha256Id); | ||||
|   if ( signingCertificateNode == NULL ) { | ||||
|     print_error("error: failed to add SigningCertificate node \n"); | ||||
|     xmlFachoPrintError("error: failed to add SigningCertificate node \n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signaturePolicyIdentifierNode = xmlXadesTmplAddSignaturePolicyIdentifier(signedSignaturePropertiesNode); | ||||
|   if ( signaturePolicyIdentifierNode == NULL ) { | ||||
|     print_error("error: failed to add PolicyIdentifier node\n"); | ||||
|     xmlFachoPrintError("error: failed to add PolicyIdentifier node\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signaturePolicyIdNode = xmlXadesTmplAddSignaturePolicyId(signaturePolicyIdentifierNode); | ||||
|   if ( signaturePolicyIdNode == NULL ) { | ||||
|     print_error("error: failed to add SignaturePolicyId node.\n"); | ||||
|     xmlFachoPrintError("error: failed to add SignaturePolicyId node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   sigPolicyIdNode = xmlXadesTmplAddSigPolicyId(signaturePolicyIdNode, policyIdIdentifier, policyIdDescription); | ||||
|   if ( sigPolicyIdNode == NULL ) { | ||||
|     print_error("error: failed to add SigPolicyId node.\n"); | ||||
|     xmlFachoPrintError("error: failed to add SigPolicyId node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   sigPolicyHashNode = xmlXadesTmplAddSigPolicyHash(signaturePolicyIdNode, xmlSecTransformSha256Id); | ||||
|   if ( sigPolicyHashNode == NULL ) { | ||||
|     print_error("error: failed to add SigPolicyHash node.\n"); | ||||
|     xmlFachoPrintError("error: failed to add SigPolicyHash node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
|   signerRoleNode = xmlXadesTmplAddSignerRole(signedSignaturePropertiesNode, BAD_CAST "supplier"); | ||||
|   if ( signerRoleNode == NULL ) { | ||||
|     print_error("error: failed to add SignerRole node.\n"); | ||||
|     xmlFachoPrintError("error: failed to add SignerRole node.\n"); | ||||
|     goto fail; | ||||
|   } | ||||
|  | ||||
| @@ -122,18 +119,18 @@ xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) { | ||||
|   return(-1); | ||||
| } | ||||
|  | ||||
| static int | ||||
| xmlXadesAppInit() { | ||||
| int | ||||
| xmlFachoInit() { | ||||
|   xmlInitParser(); | ||||
|   LIBXML_TEST_VERSION; | ||||
|    | ||||
|   if ( xmlSecInit() < 0 ) { | ||||
|     print_error("xmlsec initialization failed.\n"); | ||||
|     xmlFachoPrintError("xmlsec initialization failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecCheckVersion() != 1 ) { | ||||
|     print_error("loaded xmlsec library version is not compatible.\n"); | ||||
|     xmlFachoPrintError("loaded xmlsec library version is not compatible.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
| @@ -147,61 +144,39 @@ xmlXadesAppInit() { | ||||
| #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ | ||||
|     | ||||
|   if ( xmlSecCryptoAppInit(NULL) < 0 ) { | ||||
|     print_error("crypto initialization failed.\n"); | ||||
|     xmlFachoPrintError("crypto initialization failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecCryptoInit() < 0 ) { | ||||
|     print_error("xmlsec-crypto initialization failed.\n"); | ||||
|     xmlFachoPrintError("xmlsec-crypto initialization failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   return(0); | ||||
| } | ||||
|  | ||||
| static int | ||||
| xmlXadesAppShutdown() { | ||||
| int | ||||
| xmlFachoShutdown() { | ||||
|  | ||||
|   if ( xmlSecCryptoShutdown() < 0 ) { | ||||
|     print_error("xmlSecCryptoShutdown failed.\n"); | ||||
|     xmlFachoPrintError("xmlSecCryptoShutdown failed.\n"); | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecCryptoAppShutdown() < 0 ) { | ||||
|     print_error("xmlSecCryptoAppShutdown failed.\n"); | ||||
|     xmlFachoPrintError("xmlSecCryptoAppShutdown failed.\n"); | ||||
|   } | ||||
|    | ||||
|   if ( xmlSecShutdown() < 0 ) { | ||||
|     print_error("xmlsec shutdown failed.\n"); | ||||
|     xmlFachoPrintError("xmlsec shutdown failed.\n"); | ||||
|   } | ||||
|  | ||||
|   xmlCleanupParser(); | ||||
|   return(0); | ||||
| } | ||||
|  | ||||
| /*     | ||||
|     X509 *cert = xmlSecOpenSSLKeyDataX509GetCert(keyData, 0); | ||||
|     if (cert == NULL) { | ||||
|       print_error("xmlSecOpenSSLKeyDataX509GetKeyCert fail\n"); | ||||
|     } | ||||
|  | ||||
|     char *issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); | ||||
|  | ||||
|     printf("x509 issuer: %s\n", issuer); | ||||
|  | ||||
|     //https://stackoverflow.com/questions/9749560/how-to-calculate-x-509-certificates-sha-1-fingerprint-in-c-c-objective-c | ||||
|     unsigned char md[EVP_MAX_MD_SIZE]; | ||||
|     unsigned int n; | ||||
|     const EVP_MD *digest = EVP_get_digestbyname("sha256"); | ||||
|     X509_digest(cert, digest, md, &n); | ||||
|     printf("%s", "Fingerprint:"); | ||||
|     for(int pos = 0; pos < 19 ; pos++) { | ||||
|       printf("%02x:", md[pos]); | ||||
|     } | ||||
|     printf("%02x\n", md[19]); | ||||
| */ | ||||
|  | ||||
| static int | ||||
| xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *password) { | ||||
| int | ||||
| xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password) { | ||||
|   xmlDocPtr doc = NULL; | ||||
|   xmlNodePtr signNode = NULL; | ||||
|   xmlNodePtr refNode = NULL; | ||||
| @@ -219,14 +194,14 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw | ||||
|  | ||||
|   doc = xmlParseFile(filename); | ||||
|   if ( (doc == NULL) || (xmlDocGetRootElement(doc) == NULL) ) { | ||||
|     print_error("error: unable to parse file %s\n", filename); | ||||
|     xmlFachoPrintError("error: unable to parse file %s\n", filename); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14NId, | ||||
|                                        xmlSecTransformRsaSha256Id, NULL); | ||||
|   if ( signNode == NULL ) { | ||||
|     print_error("error: failed to create signature template.\n"); | ||||
|     xmlFachoPrintError("error: failed to create signature template.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
| @@ -238,11 +213,11 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw | ||||
|                                             BAD_CAST "", //uri | ||||
|                                             NULL); //type | ||||
|   if ( refNode == NULL ) { | ||||
|     print_error("error: failed to add reference to signature template.\n"); | ||||
|     xmlFachoPrintError("error: failed to add reference to signature template.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|   if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL ) { | ||||
|     print_error("error: failed to add enveloped transform to reference\n"); | ||||
|     xmlFachoPrintError("error: failed to add enveloped transform to reference\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
| @@ -252,72 +227,79 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw | ||||
|                                             BAD_CAST "#xmldsig-facho-KeyInfo", | ||||
|                                             NULL); | ||||
|   if ( refNode == NULL ) { | ||||
|     print_error("error: failed to add reference to signature template key-info.\n"); | ||||
|     xmlFachoPrintError("error: failed to add reference to signature template key-info.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, BAD_CAST "xmldsig-facho-KeyInfo"); | ||||
|   if ( keyInfoNode == NULL ) { | ||||
|     print_error("error: failed to add key info.\n"); | ||||
|     xmlFachoPrintError("error: failed to add key info.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   x509DataNode = xmlSecTmplKeyInfoAddX509Data(keyInfoNode); | ||||
|   if ( x509DataNode == NULL ) { | ||||
|     print_error("error: failde to add x509 DATA \n"); | ||||
|     xmlFachoPrintError("error: failde to add x509 DATA \n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   if ( xmlSecTmplX509DataAddCertificate(x509DataNode) == NULL ) { | ||||
|     print_error("error: failde to add x509Certificate node\n"); | ||||
|     xmlFachoPrintError("error: failde to add x509Certificate node\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   if ( xmlFachoTmplXadesCreate(doc, signNode) < 0 ){ | ||||
|     print_error("error: xmlFachoTmplXadesCreate failed.\n"); | ||||
|     xmlFachoPrintError("error: xmlFachoTmplXadesCreate failed.\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   dsigCtx = xmlSecDSigCtxCreate(NULL); | ||||
|   if ( dsigCtx == NULL ) { | ||||
|     print_error("error: dsig context creating failed\n"); | ||||
|     xmlFachoPrintError("error: dsig context creating failed\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|    | ||||
|  | ||||
|   // cargamos el archivo pkcs12 con llave privado y certificados x509 | ||||
|   dsigCtx->signKey = xmlSecCryptoAppKeyLoad(pkcs12name, | ||||
|                                             xmlSecKeyDataFormatPkcs12, | ||||
|                                             password, | ||||
|                                             NULL, NULL); | ||||
|   if ( dsigCtx->signKey == NULL ) { | ||||
|     print_error("error: failed to load pkcs12\n"); | ||||
|     xmlFachoPrintError("error: failed to load pkcs12\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   xmlXadesPolicyIdentifierCtx policyIdCtx; | ||||
|  | ||||
|   // por ahora el hash del identificador lo tomamos del pdf de la dian | ||||
|   policyIdCtx.contentCallback = &xmlFachoPolicyIdentifierCtxFromFilename; | ||||
|      | ||||
|   xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx, XADES_DIGEST_SHA256, &policyIdCtx); | ||||
|   if ( xadesDsigCtx == NULL ) { | ||||
|     print_error("error: xades context creating failed.\n"); | ||||
|     xmlFachoPrintError("error: xades context creating failed.\n"); | ||||
|     return(-1); | ||||
|   } | ||||
|  | ||||
|   if ( xmlXadesDSigCtxSign(xadesDsigCtx, signNode) < 0 ) { | ||||
|     print_error("error: signature failed\n"); | ||||
|   // debe existir el elemento antes del firmado | ||||
|   node = xmlFachoTmplUBLExtensionAddExtensionContent(doc); | ||||
|   if ( node == NULL ) { | ||||
|     xmlFachoPrintError("error: failed to add UBLExtensions/UBLExtension/ExtensionContent\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|   node = xmlFachoTmplUBLExtensionAddExtensionContent(doc); | ||||
|   if ( node == NULL ) { | ||||
|     print_error("error: failed to add UBLExtensions/UBLExtension/ExtensionContent\n"); | ||||
|  | ||||
|   // realizar firma de documento | ||||
|   if ( xmlXadesDSigCtxSign(xadesDsigCtx, signNode) < 0 ) { | ||||
|     xmlFachoPrintError("error: signature failed\n"); | ||||
|     goto done; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   xmlUnlinkNode(signNode); | ||||
|   xmlSecAddChildNode(node, signNode); | ||||
|  | ||||
|   xmlDocDump(stdout, doc); | ||||
|   xmlDocDump(out, doc); | ||||
|  | ||||
|   res = 0; | ||||
|  | ||||
| @@ -336,32 +318,7 @@ xmlXadesSignFile(const char *filename, const char *pkcs12name, const char *passw | ||||
|   return(res); | ||||
| } | ||||
|  | ||||
| int main(int argc, char *argv[]) { | ||||
|   basename = argv[0]; | ||||
|   int exitStatus = EXIT_SUCCESS; | ||||
|    | ||||
|   if (argc != 4) { | ||||
|     print_error("%s: <factura.xml> <pc12> <password>\n", basename); | ||||
|     return(EXIT_FAILURE); | ||||
|   } | ||||
|  | ||||
|   if ( xmlXadesAppInit() < 0 ) { | ||||
|     print_error("initialization failed.\n"); | ||||
|     return(EXIT_FAILURE); | ||||
|   } | ||||
|  | ||||
|   if ( xmlXadesSignFile( argv[1], argv[2], argv[3] ) != 0 ) { | ||||
|     print_error("%s", "fail to sign file\n"); | ||||
|     exitStatus = EXIT_FAILURE; | ||||
|   } | ||||
|  | ||||
|   xmlXadesAppShutdown();   | ||||
|   return(exitStatus); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| xmlNodePtr | ||||
| static xmlNodePtr | ||||
| xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) { | ||||
|   xmlNodePtr node = NULL; | ||||
|   xmlNodePtr parent = NULL; | ||||
| @@ -373,28 +330,30 @@ xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) { | ||||
|   if ( parent == NULL ) { | ||||
|     parent = xmlSecAddChild(xmlDocGetRootElement(doc), ublExtensionsName,  ublExtensionDSigNs); | ||||
|     if ( parent == NULL ) { | ||||
|       print_error("error: failed to cleate UBLExtensions.\n"); | ||||
|       xmlFachoPrintError("error: failed to cleate UBLExtensions.\n"); | ||||
|       return(NULL); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // adicionamos nuevo elemento UBLExtension | ||||
|   node = xmlSecAddChild(parent, ublExtensionName, ublExtensionDSigNs); | ||||
|   if ( node == NULL ) { | ||||
|     print_error("error: failed to add UBLExtension\n"); | ||||
|     xmlFachoPrintError("error: failed to add UBLExtension\n"); | ||||
|     xmlFreeNode(parent); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   // adicionamos nuevo elemento ExtensionContent | ||||
|   node = xmlSecAddChild(node, extensionContentName, ublExtensionDSigNs); | ||||
|   if ( node == NULL ) { | ||||
|     print_error("error: failed to add ExtensionContent"); | ||||
|     xmlFachoPrintError("error: failed to add ExtensionContent"); | ||||
|     return(NULL); | ||||
|   } | ||||
|  | ||||
|   return(node); | ||||
| } | ||||
|  | ||||
| int | ||||
| static int | ||||
| xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *policyId, xmlSecBufferPtr buffer) { | ||||
|   static unsigned char politicafirmav2[] = { | ||||
|     /** | ||||
|   | ||||
							
								
								
									
										15
									
								
								experimental/facho-signer/src/facho_signer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								experimental/facho-signer/src/facho_signer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| #ifndef FACHO_SIGNER_H | ||||
| #define FACHO_SIGNER_H | ||||
|  | ||||
| #include <stdio.h> | ||||
|  | ||||
| int | ||||
| xmlFachoInit(); | ||||
|  | ||||
| int | ||||
| xmlFachoShutdown(); | ||||
|  | ||||
| int | ||||
| xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password); | ||||
|  | ||||
| #endif /* FACHO_SIGNER_H */ | ||||
							
								
								
									
										32
									
								
								experimental/facho-signer/src/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								experimental/facho-signer/src/main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| #include "xades/xades.h" | ||||
| #include "facho_signer.h" | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
|  | ||||
| static char *basename = NULL; | ||||
|  | ||||
| int main(int argc, char *argv[]) { | ||||
|   int exitStatus = EXIT_SUCCESS; | ||||
|  | ||||
|   basename = argv[0]; | ||||
|    | ||||
|   if (argc != 4) { | ||||
|     fprintf(stderr, "%s: <factura.xml> <pc12> <password>\n", basename); | ||||
|     return(EXIT_FAILURE); | ||||
|   } | ||||
|  | ||||
|   if ( xmlFachoInit() < 0 ) { | ||||
|     fprintf(stderr, "initialization failed.\n"); | ||||
|     return(EXIT_FAILURE); | ||||
|   } | ||||
|  | ||||
|   if ( xmlFachoSignFile( stdout, argv[1], argv[2], argv[3] ) != 0 ) { | ||||
|     fprintf(stderr, "fail to sign file\n"); | ||||
|     exitStatus = EXIT_FAILURE; | ||||
|   } | ||||
|  | ||||
|   xmlFachoShutdown();   | ||||
|   return(exitStatus); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user