Last active
December 27, 2021 22:09
-
-
Save avafinger/d2e2007d3ed87c452fa0c0b184dd11fa to your computer and use it in GitHub Desktop.
libpodofo memory leak (some cleanup - UPDATED)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// | |
// ===================================================================== | |
// g++ sign.cpp -o sign -I/usr/include/openssl -lssl -lpodofo -lcrypto | |
// ===================================================================== | |
// | |
// OpenSSL includes | |
#include <openssl/err.h> | |
#include <openssl/evp.h> | |
#include <openssl/pkcs12.h> | |
#include <openssl/pkcs7.h> | |
#include <openssl/rsa.h> | |
#include <openssl/sha.h> | |
#include <podofo/podofo.h> | |
#include <iostream> | |
using namespace PoDoFo; | |
class Ossl { | |
private: | |
SHA_CTX m_sha_ctx; | |
EVP_PKEY* mp_pkey; // private key | |
X509* mp_x509; // signing certificate | |
STACK_OF(X509)* mp_ca; // certificate chain up to the CA | |
unsigned char * mp_p7Buf; | |
public: | |
Ossl(){} | |
~Ossl(){} | |
void init(const char * file, const char * passwd) { | |
OPENSSL_malloc_init(); | |
ERR_load_crypto_strings(); | |
OpenSSL_add_all_algorithms(); | |
FILE* fp = fopen(file, "rb"); | |
if (fp == NULL) { | |
std::cout << "fp null" << std::endl; | |
return; | |
} | |
PKCS12* p12 = d2i_PKCS12_fp(fp, NULL); | |
fclose(fp); | |
if (p12 == NULL) { | |
std::cout << "p12 null" << std::endl; | |
return; | |
} | |
mp_pkey = NULL; | |
mp_x509 = NULL; | |
mp_ca = NULL; | |
int ok = PKCS12_parse(p12, passwd, &mp_pkey, &mp_x509, &mp_ca); | |
if (ok == 0) { | |
std::cout << "not ok" << std::endl; | |
return; | |
} | |
PKCS12_free(p12); | |
SHA1_Init(&m_sha_ctx); | |
std::cout << "init ok" << std::endl; | |
} | |
void close() { | |
if (mp_ca) | |
sk_X509_pop_free(mp_ca, X509_free); | |
if (mp_x509) { | |
X509_free(mp_x509); | |
} | |
if (mp_pkey) { | |
EVP_PKEY_free(mp_pkey); | |
} | |
if (mp_p7Buf) { | |
free(mp_p7Buf); | |
} | |
ERR_free_strings(); | |
} | |
void append(const char* data, int len) { | |
SHA1_Update(&m_sha_ctx, data, len); | |
return; | |
} | |
char * signature() { | |
unsigned char sha_buffer[SHA_DIGEST_LENGTH]; | |
memset((void*) sha_buffer, 0, SHA_DIGEST_LENGTH); | |
SHA1_Final(sha_buffer, &m_sha_ctx); | |
PKCS7* p7 = PKCS7_new(); | |
PKCS7_set_type(p7, NID_pkcs7_signed); | |
PKCS7_SIGNER_INFO* p7Si = PKCS7_add_signature(p7, mp_x509, mp_pkey, EVP_sha1()); | |
PKCS7_add_attrib_content_type(p7Si, OBJ_nid2obj(NID_pkcs7_data)); | |
PKCS7_add0_attrib_signing_time(p7Si, NULL); | |
PKCS7_add1_attrib_digest(p7Si, (const unsigned char*) sha_buffer, SHA_DIGEST_LENGTH); | |
PKCS7_add_certificate(p7, mp_x509); | |
int c = 0; | |
for ( ; c < sk_X509_num(mp_ca); c++) { | |
X509* cert = sk_X509_value(mp_ca, c); | |
PKCS7_add_certificate(p7, cert); | |
} | |
PKCS7_set_detached(p7, 1); | |
PKCS7_content_new(p7, NID_pkcs7_data); | |
PKCS7_SIGNER_INFO_sign(p7Si); | |
mp_p7Buf = NULL; | |
int p7Len = i2d_PKCS7(p7, NULL); | |
unsigned char* p7Buf = (unsigned char*) calloc(1, p7Len + 1); | |
if (p7Buf != NULL) { | |
mp_p7Buf = p7Buf; | |
i2d_PKCS7(p7, &p7Buf); | |
std::cout << "p7Buf filled"; | |
} | |
PKCS7_free(p7); | |
return (char *) p7Buf; | |
} | |
}; | |
using namespace PoDoFo; | |
#define CONVERSION_CONSTANT 0.002834645669291339 | |
void CreateSimpleForm( PdfPage* pPage, PdfStreamedDocument* pDoc, const PdfData &signatureData ) | |
{ | |
PdfPainter painter; | |
PdfFont* pFont = pDoc->CreateFont( "Courier" ); | |
painter.SetPage( pPage ); | |
painter.SetFont( pFont ); | |
painter.DrawText( 10000 * CONVERSION_CONSTANT, 280000 * CONVERSION_CONSTANT, "PoDoFo Sign Test" ); | |
painter.FinishPage(); | |
PdfSignatureField signField( pPage, PdfRect( 70000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, | |
50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ), pDoc ); | |
signField.SetFieldName("SignatureFieldName"); | |
signField.SetSignature(signatureData); | |
signField.SetSignatureReason("I agree"); | |
} | |
int main( int argc, char* argv[] ) | |
{ | |
PdfPage* pPage; | |
if( argc != 4 ) | |
{ | |
printf("Usage: sign [output_filename] [pfx certificate] [password]\n"); | |
printf(" - Create a PDF ready to be signed\n"); | |
return 0; | |
} | |
PdfSignOutputDevice signer(argv[1]); | |
// Reserve space for signature | |
signer.SetSignatureSize(1024); | |
PdfStreamedDocument writer( &signer, PoDoFo::ePdfVersion_1_5 ); | |
// Disable default appearance | |
writer.GetAcroForm(ePdfCreateObject, ePdfAcroFormDefaultAppearance_None); | |
pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); | |
CreateSimpleForm( pPage, &writer, *signer.GetSignatureBeacon()); | |
writer.Close(); | |
// Adjust ByteRange for signature | |
if(signer.HasSignaturePosition()) { | |
signer.AdjustByteRange(); | |
// read data for signature and count it | |
signer.Seek(0); | |
Ossl * ossl = new Ossl(); | |
ossl->init(argv[2], argv[3]); | |
// generate digest and count signature | |
// use NSS, MS Crypto API or OpenSSL | |
// to generate signature in DER format | |
char buff[65536]; | |
size_t len; | |
while( (len = signer.ReadForSignature(buff, 65536))>0 ) | |
{ | |
ossl->append(buff, len); | |
} | |
// Paste signature to the file | |
PdfData sigData(ossl->signature()); | |
signer.SetSignature(sigData); | |
ossl->close(); | |
delete ossl; | |
} | |
signer.Flush(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add ossl->close();