How to Check Whether the resources of X509 has been freed when it is freed by X509_free()

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

How to Check Whether the resources of X509 has been freed when it is freed by X509_free()

Erwin Himawan
Hi All,

I have several questions associated with freeing resources of X509 struct.

snippet of my code:
X509 *x509Cert = X509_new();
if (x509Cert == NULL) printf("Error instantiating X509 object\n");

/* do some processing with my x509Cert object */

/* Cleaning up resources of x509Cert */
if(x509Cert != NULL) X509_free(x509Cert);

My questions are:
1. How to check that x509Cert resources have been freed?  I notice that X509_free(x509Cert) does not set the x509Cert to NULL, therefore I can not rely on if(x509Cert != NULL) to verify that x509Cert resources has been freed.  this a bug or there are other method for verifying whether x509Cert resources have been freed.
2. Does X509_free() also free all the internal objects that are part of the X509 struct; e.g. X509_ALGOR, X509_NAME, ASN1_INTEGER, ASN1_TIME, etc

Thanks,
Erwin
Reply | Threaded
Open this post in threaded view
|

Re: How to Check Whether the resources of X509 has been freed when it is freed by X509_free()

Jakob Bohm-7
On 9/9/2011 5:21 AM, Erwin Himawan wrote:

> Hi All,
> I have several questions associated with freeing resources of X509 struct.
> snippet of my code:
> X509 *x509Cert = X509_new();
> if (x509Cert == NULL) printf("Error instantiating X509 object\n");
> /* do some processing with my x509Cert object */
> /* Cleaning up resources of x509Cert */
> if(x509Cert != NULL) X509_free(x509Cert);
> My questions are:
> 1. How to check that x509Cert resources have been freed? I notice that
> X509_free(x509Cert) does not set the x509Cert to NULL, therefore I can not
> rely on if(x509Cert != NULL) to verify that x509Cert resources has been
> freed. this a bug or there are other method for verifying whether x509Cert
> resources have been freed.
As OpenSSL is a C (not C++ or Pascal) API, unless a function takes an
explicit pointer to your x509Cert variable it is not supposed to have the
ability to change it.  This is one of the nice semantic guarantees of the
C language.

As x509_free() returns void, you should simply assume that the call
*will* free what it is told to free, to the maximum extent reasonably
possible, which is actually the sanest and most programmer friendly way
to specify a cleanup function (for the same reason, C++ destructors have
no return value either and are barred from using exceptions during stack
unwind). It is good practice to wrap it in a block such as the
following: {    X509 *ptmp = x509Cert;    x509Cert = NULL; // Do this
first to reduce risk of race conditions // in your own multithreading    
x509_free(tmp); } Or in C++ you could declare a macro-assisted smart
pointer type similar to the following: (NOT TESTED!) (For C++ purists:
the macros are used to do the name pasting needed to refer to individual
per-type global function names and to generate obvious class names such
as X509Ptr, all the real work is done by the C++ template).

#define ASNPTR_TYP(typ) ASNPtr<type, typ##_new, typ##_free> #define
DECLARE_ASNPTR(typ) typedef ASNPTR_TYP(typ) typ##Ptr; class ASNPTRBase {
protected: void *p; public: typedef ASNPTRBase Self; typedef Self*
PSelf; typedef void *PTYP; protected:  PTYP Take(void) { PTYP p1 = p; p
= 0; return p1; }    ASNPtrBase(): p(0) {}    ASNPtrBase(PTYP p1) p(p1)
{} ASNPTRBase(Self &p1) p(p1.Take()) {}    ~ASNPTRBase() { } public:
bool operator bool() const { return !!p; } PTYP operator PTYP() const {
return p; } private:  Self & operator = (PTYP p1) {}; // Not available,
do not generate default impl. Self & operator = (Self &p1) {};  // Not
available, do not generate default impl. }; template < class ASNT, ASNT*
(*ASNT_new)(void), void (*ASNT_free)(ASNT *p) > class ASNPtr: public
ASNPTRBase {   public: typedef ASNPtr Self; typedef Self *PSelf; typedef
ASNT * PTYP; PTYP Take(void) { return (PTYP)ASNPTRBase::Take(); }    
void Free(void) { // Must be in template because of type-specic specific
call PTYP p1 = Take(); if (p1) ASNT_free(p1); } ASNPtr &Alloc(void) { //
Must be in template to avoid adding a vptr to the size of ASNPtrBase
objects Free(); p = ASNT_new(); } ASNPtr &Set(PTYP p1) { // Must be in
template to avoid adding a vptr to the size of ASNPtrBase objects
Free(); p = p1; } ASNPtr &Set(ASNPtr &p1) { return Set(p1.Take()); }    
ASNPtr() {}    ASNPtr(PTYP p1) ASNPTRBase(p1) {} ASNPtr(ASNPtr&p1)
ASNPtrBase(p1) {}    ~ASNPtr() { Free(); } Self& operator = (PTYP p1) {
return Set(p1); } Self& operator = (Self &p1) { return Set(p1); } PTYP
operator PTYP() const { return p; } private: Self& operator = (const
Self &p1) {} // Not available, do not generate default impl. // do not
generate call to operator=(p1.operator PTYP()) // for const source
objects as that would ruin the // rule that only one ASNPTR can own the
object at // any given time. } DECLARE_ASNPTR(X509)
DECLARE_ASNPTR(X509_NAME) DECLARE_ASNPTR(X509_CRL) // etc.


> 2. Does X509_free() also free all the internal objects that are part of the
> X509 struct; e.g. X509_ALGOR, X509_NAME, ASN1_INTEGER, ASN1_TIME, etc
> Thanks,
> Erwin
Please look at the source code of the function ASN1_item_free, which does
the real work.


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: How to Check Whether the resources of X509 has been freed when it is freed by X509_free()

Erwin Himawan
Thanks for the explanation and pinter for the relevant ASN1 function.

Erwin

--------------------------------------------------
From: "Jakob Bohm" <[hidden email]>
Sent: Friday, September 09, 2011 4:22 AM
To: <[hidden email]>
Subject: Re: How to Check Whether the resources of X509 has been freed when
it is freed by X509_free()

> On 9/9/2011 5:21 AM, Erwin Himawan wrote:
>> Hi All,
>> I have several questions associated with freeing resources of X509
>> struct.
>> snippet of my code:
>> X509 *x509Cert = X509_new();
>> if (x509Cert == NULL) printf("Error instantiating X509 object\n");
>> /* do some processing with my x509Cert object */
>> /* Cleaning up resources of x509Cert */
>> if(x509Cert != NULL) X509_free(x509Cert);
>> My questions are:
>> 1. How to check that x509Cert resources have been freed? I notice that
>> X509_free(x509Cert) does not set the x509Cert to NULL, therefore I can
>> not
>> rely on if(x509Cert != NULL) to verify that x509Cert resources has been
>> freed. this a bug or there are other method for verifying whether
>> x509Cert
>> resources have been freed.
> As OpenSSL is a C (not C++ or Pascal) API, unless a function takes an
> explicit pointer to your x509Cert variable it is not supposed to have the
> ability to change it.  This is one of the nice semantic guarantees of the
> C language.
>
> As x509_free() returns void, you should simply assume that the call *will*
> free what it is told to free, to the maximum extent reasonably possible,
> which is actually the sanest and most programmer friendly way to specify a
> cleanup function (for the same reason, C++ destructors have no return
> value either and are barred from using exceptions during stack unwind). It
> is good practice to wrap it in a block such as the following: {    X509
> *ptmp = x509Cert;    x509Cert = NULL; // Do this first to reduce risk of
> race conditions // in your own multithreading    x509_free(tmp); } Or in
> C++ you could declare a macro-assisted smart pointer type similar to the
> following: (NOT TESTED!) (For C++ purists: the macros are used to do the
> name pasting needed to refer to individual per-type global function names
> and to generate obvious class names such as X509Ptr, all the real work is
> done by the C++ template).
>
> #define ASNPTR_TYP(typ) ASNPtr<type, typ##_new, typ##_free> #define
> DECLARE_ASNPTR(typ) typedef ASNPTR_TYP(typ) typ##Ptr; class ASNPTRBase {
> protected: void *p; public: typedef ASNPTRBase Self; typedef Self* PSelf;
> typedef void *PTYP; protected:  PTYP Take(void) { PTYP p1 = p; p = 0;
> return p1; }    ASNPtrBase(): p(0) {}    ASNPtrBase(PTYP p1) p(p1) {}
> ASNPTRBase(Self &p1) p(p1.Take()) {}    ~ASNPTRBase() { } public: bool
> operator bool() const { return !!p; } PTYP operator PTYP() const { return
> p; } private:  Self & operator = (PTYP p1) {}; // Not available, do not
> generate default impl. Self & operator = (Self &p1) {};  // Not available,
> do not generate default impl. }; template < class ASNT, ASNT*
> (*ASNT_new)(void), void (*ASNT_free)(ASNT *p) > class ASNPtr: public
> ASNPTRBase {   public: typedef ASNPtr Self; typedef Self *PSelf; typedef
> ASNT * PTYP; PTYP Take(void) { return (PTYP)ASNPTRBase::Take(); }    void
> Free(void) { // Must be in template because of type-specic specific call
> PTYP p1 = Take(); if (p1) ASNT_free(p1); } ASNPtr &Alloc(void) { // Must
> be in template to avoid adding a vptr to the size of ASNPtrBase objects
> Free(); p = ASNT_new(); } ASNPtr &Set(PTYP p1) { // Must be in template to
> avoid adding a vptr to the size of ASNPtrBase objects Free(); p = p1; }
> ASNPtr &Set(ASNPtr &p1) { return Set(p1.Take()); }    ASNPtr() {}
> ASNPtr(PTYP p1) ASNPTRBase(p1) {} ASNPtr(ASNPtr&p1) ASNPtrBase(p1) {}
> ~ASNPtr() { Free(); } Self& operator = (PTYP p1) { return Set(p1); } Self&
> operator = (Self &p1) { return Set(p1); } PTYP operator PTYP() const {
> return p; } private: Self& operator = (const Self &p1) {} // Not
> available, do not generate default impl. // do not generate call to
> operator=(p1.operator PTYP()) // for const source objects as that would
> ruin the // rule that only one ASNPTR can own the object at // any given
> time. } DECLARE_ASNPTR(X509) DECLARE_ASNPTR(X509_NAME)
> DECLARE_ASNPTR(X509_CRL) // etc.
>
>
>> 2. Does X509_free() also free all the internal objects that are part of
>> the
>> X509 struct; e.g. X509_ALGOR, X509_NAME, ASN1_INTEGER, ASN1_TIME, etc
>> Thanks,
>> Erwin
> Please look at the source code of the function ASN1_item_free, which does
> the real work.
>
>
> ______________________________________________________________________
> OpenSSL Project                                 http://www.openssl.org
> User Support Mailing List                    [hidden email]
> Automated List Manager                           [hidden email]

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]