On Mon, 19 Apr 2010, Matthew Grooms wrote:
On 3/31/2010 7:44 AM, Michael wrote:

Hello list,

I'm using the shrew ike daemon (packaged with the Qt client) version
2.1.4 on Ubuntu Linux 9.10. The goal is a roadwarrior installation
with X.509 certificate authentication.

When using preshared keys this same configuration works. Mobile
clients using other software (IPSecuritas) with the same
certificates I'm loading in Shrew work as well so...

The problem is that I see 'Gateway authentication error' in the
GUI window after trying to connect. The log /var/log/iked.log:

   ii : unable to get local issuer certificate(20) at depth:0
   ii : subject :/CN=name.host.tld
   !! : unable to verify remote peer certificate

The host 'name.host.tld' is in the SubjectAltName of the X.509
certificate loaded on the ike v1 server m0n0wall 1.31. I have
concatanated the root and intermediate CA certificates of CaCert.org
to the file 'cacert-combi.pem':

s:ident-server-type:asn1dn
s:auth-server-cert:/home/username/.ike/certs/cacert-combi.pem
s:auth-client-cert:/home/username/.ike/certs/myclienthost-cacert-rsa-4096-crt.pem
s:auth-client-key:/home/username/.ike/keys/myclienthost-cacert-rsa-4096-key.pem

What can be the problem?


I don't believe concatenating the certificate files together will have
any effect. A lot of work was done between 2.1.4 and 2.1.6 to handle a
multi-certificate chain to be interpreted correctly when received from
the peer during phase1 negotiations. And on the windows platform, we
have a special directory where a user can drop additional certificates
that are used as intermediates during certificate verification. But on
Linux/BSD, there is no analog to this.

  Did you try the attached patch I've sent you a few years ago?  I believe
it supports chained/concatnated certificate inside a single .pem file.
Even better, it also supports .p12 file that includes user's key pair and
complete CA certificate chain.

  Given that this patch only utilises standard OpenSSL APIs, it should be
portable amongst WIN32 and UN*X Shrew VPN implementations.

I think we need to allow a certificate directory to be passed instead of
a single certificate file. This will allow a client to configure a group
of certificate files that can be used for chained authentication.
Unfortunately, I don't have time to do this at the moment. This should
be completed before 2.2.0 release. Sorry I can't be more help at this time.

  IMHO, the problem in directory based certificate storage is that there're
multiple directories which can be confusing to users. I've run into this in 2.1.0(not sure if it is fixed in recent release) since I put the chained .pem into 'My Document/Shrew .../certificate' rather than 'Program Files/Shrew VPN/certificate.' The former path didn't seem to be in ShrewVPN's default ceritificate search path and thus caused failure in subsequent server certificate verification process.
diff -rup ike.orig/source/iked/iked.h ike/source/iked/iked.h
--- ike.orig/source/iked/iked.h 2008-06-10 10:13:52.000000000 +0800
+++ ike/source/iked/iked.h      2008-08-06 17:59:08.000000000 +0800
@@ -547,12 +551,17 @@ typedef class _IKED

        // x.509 certificate helper functions

 

        bool    cert_2_bdata( BDATA & cert, X509 * x509 );

+       bool    certs_2_bdata( BDATA & certs, STACK_OF(X509) * x509_chain );

        bool    bdata_2_cert( X509 ** x509, BDATA & cert );

+       bool    bdata_2_certs( STACK_OF(X509) ** x509_chain, BDATA & cert );

 

        long    cert_save( BDATA & cert, char * fpath );

        long    cert_load( BDATA & cert, char * fpath, bool ca, BDATA & pass );

        bool    cert_load_pem( BDATA & cert, FILE * fp, bool ca, BDATA & pass );

        bool    cert_load_p12( BDATA & cert, FILE * fp, bool ca, BDATA & pass );

+       long    certs_load( BDATA & certs, char * fpath, bool ca, BDATA & pass 
);

+       bool    certs_load_pem( BDATA & certs, FILE * fp, bool ca, BDATA & pass 
);

+       bool    certs_load_p12( BDATA & certs, FILE * fp, bool ca, BDATA & pass 
);

        bool    cert_desc( BDATA & cert, BDATA & text );

        bool    cert_subj( BDATA & cert, BDATA & subj );

        bool    asn1_text( BDATA & asn1, BDATA & text );

diff -rup ike.orig/source/iked/ike.io.admin.cpp ike/source/iked/ike.io.admin.cpp
--- ike.orig/source/iked/ike.io.admin.cpp       2008-05-19 05:35:53.000000000 
+0800
+++ ike/source/iked/ike.io.admin.cpp    2008-08-06 18:20:58.000000000 +0800
@@ -406,7 +406,7 @@ long _IKED::loop_ipc_client( IKEI * ikei
 

                                                        log.txt( LLOG_INFO, "<A 
: remote cert \'%s\' message\n", text.text() );

 

-                                                       long loaded = 
cert_load( tunnel->peer->cert_r, text.text(), true, tunnel->peer->fpass );

+                                                       long loaded = 
certs_load( tunnel->peer->cert_r, text.text(), true, tunnel->peer->fpass );

 

                                                        switch( loaded )

                                                        {

diff -rup ike.orig/source/iked/ike.keyfile.cpp ike/source/iked/ike.keyfile.cpp
--- ike.orig/source/iked/ike.keyfile.cpp        2008-02-20 15:10:05.000000000 
+0800
+++ ike/source/iked/ike.keyfile.cpp     2008-08-06 18:44:32.000000000 +0800
@@ -79,6 +79,21 @@ bool _IKED::cert_2_bdata( BDATA & cert, 
        return true;

 }

 

+bool _IKED::certs_2_bdata( BDATA & certs, STACK_OF(X509) * x509_chain )

+{

+       int size = i2d_ASN1_SET_OF_X509(x509_chain, NULL, i2d_X509,

+           V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, IS_SEQUENCE);

+

+       certs.size( size );

+

+       unsigned char * cert_buff = certs.buff();

+       if( i2d_ASN1_SET_OF_X509(x509_chain, &cert_buff, i2d_X509,

+           V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, IS_SEQUENCE) < size )

+               return false;

+

+       return true;

+}

+

 bool _IKED::bdata_2_cert( X509 ** x509, BDATA & cert )

 {

        X509CONST unsigned char * cert_buff = cert.buff();

@@ -90,6 +105,123 @@ bool _IKED::bdata_2_cert( X509 ** x509, 
        return true;

 }

 

+bool _IKED::bdata_2_certs( STACK_OF(X509) ** x509_chain, BDATA & certs )

+{

+       X509CONST unsigned char * cert_buff = certs.buff();

+

+       *x509_chain = d2i_ASN1_SET_OF_X509( NULL, &cert_buff,

+           ( long ) certs.size(), d2i_X509, X509_free,

+           V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);

+

+       if( *x509_chain == NULL )

+               return false;

+

+       return true;

+}

+

+long _IKED::certs_load( BDATA & certs, char * fpath, bool ca, BDATA & pass )

+{

+#ifdef WIN32

+

+       FILE * fp;

+       if( fopen_s( &fp, fpath, "rb" ) )

+               return FILE_PATH;

+

+#else

+

+       FILE * fp = fopen( fpath, "rb" );

+       if( !fp )

+               return FILE_PATH;

+

+#endif

+

+       bool loaded = certs_load_pem( certs, fp, ca, pass );

+       if( !loaded )

+               loaded = certs_load_p12( certs, fp, ca, pass );

+

+       fclose( fp );

+

+       if( !loaded )

+               return FILE_FAIL;

+

+       return FILE_OK;

+}

+

+bool _IKED::certs_load_pem( BDATA & certs, FILE * fp, bool ca, BDATA & pass )

+{

+       fseek( fp, 0, SEEK_SET );

+

+       STACK_OF(X509) *cert_chain = sk_X509_new_null();

+       STACK_OF(X509_INFO) *allcerts = NULL;

+

+       allcerts = PEM_X509_INFO_read(fp, NULL, keyfile_cb, &pass);

+       if (allcerts == NULL || sk_X509_INFO_num(allcerts) == 0)

+       {

+               sk_X509_free(cert_chain);

+               return (false);

+       }

+       for (int i = 0; i < sk_X509_INFO_num(allcerts); i++)

+       {

+               X509_INFO *xi = sk_X509_INFO_value (allcerts, i);

+               if (xi->x509)

+               {

+                       sk_X509_push(cert_chain, xi->x509);

+                       xi->x509 = NULL;

+               }

+       }

+

+       certs_2_bdata( certs, cert_chain );

+

+       sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
+

+       return (true);

+}

+

+bool _IKED::certs_load_p12( BDATA & certs, FILE * fp, bool ca, BDATA & pass )

+{

+       fseek( fp, 0, SEEK_SET );

+

+       PKCS12 * p12 = d2i_PKCS12_fp( fp, NULL );

+       if( p12 == NULL )

+               return false;

+

+       X509 * x509 = NULL;

+

+       BDATA passnull;

+       passnull.set( pass );

+       passnull.add( 0, 1 );

+

+       if( ca )

+       {

+               STACK_OF( X509 ) * stack = NULL;

+

+               if( PKCS12_parse( p12, ( const char * ) passnull.buff(), NULL, 
NULL, &stack ) )

+               {

+                       if ( stack == NULL )

+                       {

+                               PKCS12_free( p12 );

+                               return false;

+                       }

+                       certs_2_bdata( certs, stack );

+                       sk_X509_free( stack );

+                       PKCS12_free( p12 );

+                       return true;

+               }

+       }

+       else

+               PKCS12_parse( p12, ( const char * ) passnull.buff(), NULL, 
&x509, NULL );

+

+       PKCS12_free( p12 );

+

+       if( x509 == NULL )

+               return false;

+

+       cert_2_bdata( certs, x509 );

+       X509_free( x509 );

+

+       return true;

+}

+

 long _IKED::cert_load( BDATA & cert, char * fpath, bool ca, BDATA & pass )

 {

 #ifdef WIN32

@@ -566,14 +698,17 @@ bool _IKED::cert_verify( IDB_LIST_CERT &
        // load ca and add to store

        //

 

-       X509 * x509_ca;

-       if( !bdata_2_cert( &x509_ca, ca ) )

+       STACK_OF(X509) * x509_ca;

+       if( !bdata_2_certs( &x509_ca, ca ) )

        {

                X509_STORE_free( store );

                return false;

        }

 

-       X509_STORE_add_cert( store, x509_ca );

+       for (int i = 0; i < sk_X509_num(x509_ca); i++)

+       {

+               X509_STORE_add_cert( store, sk_X509_value(x509_ca, i) );

+       }

 

 #ifdef WIN32

 

@@ -678,7 +837,7 @@ bool _IKED::cert_verify( IDB_LIST_CERT &
        // cleanup

        //

 

-       X509_free( x509_ca );

+       sk_X509_free( x509_ca );

        X509_STORE_free( store );

 

        return ( result > 0 );

_______________________________________________
vpn-help mailing list
[email protected]
http://lists.shrew.net/mailman/listinfo/vpn-help

Reply via email to