[squid-users] Ssl-Bump and revoked server certificates

Walter H. Walter.H at mathemainzel.info
Sun Oct 18 19:37:29 UTC 2015


On 04.10.2015 21:08, Walter H. wrote:
> Hello,
>
> does anybody know if squid does certificate checks and how to tell 
> squid to do so;
>
> this is a site with a revoked certificate
> https://revoked.grc.com/
>
> without squid, the browser shows that the certificate is revoked and 
> doesn't show the page
> with squid, the page is shown ...
>
> Thanks,
> Walter

I have solved it:

my solution not only does certificate checks using OCSP, it also stores 
the real certificates into a different "database" folder;
if someone doesn't want this, just remove the few lines of the shell script;
as there exist no CA that allows IP adresses neither in certificate 
subject nor in the SAN (subject alternative name),

https://www.whitehouse.gov/
(is blocked at my solution because of a root certificate not in the cert 
store)

all these candidates are blocked with error

/X509_V_ERR_CERT_REJECTED/

it uses two components:

- a shell script (BASH) called by the programme
- the main programme (in C): the only missing is an exception list of 
domains/hosts not to validate through this procedure

the squid.conf is expanded by these lines:

<squid.conf>
acl certSelfSigned ssl_error X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
acl certHasExpired ssl_error X509_V_ERR_CERT_HAS_EXPIRED
acl certNotValid ssl_error X509_V_ERR_CERT_NOT_YET_VALID
acl certRejected ssl_error X509_V_ERR_CERT_REJECTED
acl certRevoked ssl_error X509_V_ERR_CERT_REVOKED
acl certUntrusted ssl_error X509_V_ERR_CERT_UNTRUSTED

acl certSelfSignedChain ssl_error X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
acl certChainTooLong ssl_error X509_V_ERR_CERT_CHAIN_TOO_LONG
acl certPathLengthExceeded ssl_error X509_V_ERR_PATH_LENGTH_EXCEEDED

acl certSignatureFailure ssl_error X509_V_ERR_CERT_SIGNATURE_FAILURE
acl crlSignatureFailure ssl_error X509_V_ERR_CRL_SIGNATURE_FAILURE

acl caInvalid ssl_error X509_V_ERR_INVALID_CA

acl squidDomainMismatch ssl_error SQUID_X509_V_ERR_DOMAIN_MISMATCH
acl squidInfiniteValidation ssl_error SQUID_X509_V_ERR_INFINITE_VALIDATION
acl squidSslHandshake ssl_error SQUID_ERR_SSL_HANDSHAKE

sslproxy_cert_adapt setValidBefore all   ; I have these two, but they 
are not needed;
sslproxy_cert_adapt setValidAfter all

sslproxy_cert_error deny certSelfSigned
sslproxy_cert_error deny certRejected
sslproxy_cert_error deny certRevoked
sslproxy_cert_error deny certHasExpired
sslproxy_cert_error deny certNotValid
sslproxy_cert_error deny certUntrusted
sslproxy_cert_error deny certSelfSignedChain
sslproxy_cert_error deny certChainTooLong
sslproxy_cert_error deny certPathLengthExceeded
sslproxy_cert_error deny certSignatureFailure
sslproxy_cert_error deny crlSignatureFailure
sslproxy_cert_error deny caInvalid
sslproxy_cert_error deny squidDomainMismatch
sslproxy_cert_error deny squidInfiniteValidation
sslproxy_cert_error deny squidSslHandshake
sslproxy_cert_error allow all

sslcrtvalidator_program cache=8192 ttl=240 
/usr/lib64/squid/ssl_crtvalid/main.sh
sslcrtvalidator_children 12 startup=5 idle=1 concurrency=1
</squid.conf>

this main.sh script is only

<main.sh>
#!/bin/sh
/usr/lib64/squid/ssl_crtvalid/helper 2>>/tmp/crtvalid-debug.log
</main.sh>
when someone compiles the programme without _DEBUG
then the line in squid.conf would be without this

sslcrtvalidator_program cache=8192 ttl=240 
/usr/lib64/squid/ssl_crtvalid/helper

the shellscript  verify.sh is

<verify.sh>
#!/bin/sh

CAFILE=/etc/pki/tls/certs/ca-bundle.trust.crt
DTABASE=/var/local/squid/ssl_crtvalid

CERT=$1
CHAIN=$3
ISSUER=$2
SSLHOST=$4

openssl verify -CAfile $CAFILE -untrusted $CHAIN $CERT

OCSPURL=$(openssl x509 -in $CERT -noout -ocsp_uri)

if [ "$OCSPURL" == "" ];
then
   echo "$CERT: rejected"
else
   OCSPHOST=$(echo "$OCSPURL" |gawk -F\/ '{ print $3 }' -)
   openssl ocsp -CAfile $CAFILE -no_nonce -noverify -issuer $ISSUER 
-cert $CERT -url "$OCSPURL" -header Host $OCSPHOST |grep "$CERT"
fi

FINGERPRINT=$(openssl x509 -in $CERT -noout -sha1 -fingerprint |sed 
"{s/SHA1\ Fingerprint\=//g;s/\://g}")
SUBJECT=$( openssl x509 -in $CERT -noout -subject |sed "{s/subject\=\ //g}")

if [ -f $DTABASE/certs/$FINGERPRINT.pem ];
then
   ENTRY=$(cat $DTABASE/index.txt |grep "$SSLHOST" |grep "$FINGERPRINT")
   if [ "$ENTRY" == "" ];
   then
     echo -e -n "$SSLHOST\t$SUBJECT\t$FINGERPRINT.pem\n" 
 >>$DTABASE/index.txt
   fi
else
   openssl x509 -in $CERT -out $DTABASE/certs/$FINGERPRINT.pem
   echo -e -n "$SSLHOST\t$SUBJECT\t$FINGERPRINT.pem\n" >>$DTABASE/index.txt
fi
</verify.sh>

<helper.c>
/*
  * Squid SSL Validator helper programme
  *
  */

#include <ctype.h>
#include <fcntl.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>

#include <unistd.h>

#define _DEBUG

#ifdef _DEBUG
#define DEBUGINIT( ) debugInit( __LINE__ )
#define DEBUGOUT2( val, len ) debugWrite( (const void*) ( val ), len )
#define DEBUGOUT( szval ) debugWrite( (const void*) ( szval ), strlen( 
szval ) )
#define DEBUGOUTINT( intval ) debugOutputInt( __LINE__, #intval, intval )
#define DEBUGOUTSZ( szval ) debugOutputStr( __LINE__, #szval, szval )
#else
#define DEBUGINIT( )
#define DEBUGOUT2( val, len )
#define DEBUGOUT( szval )
#define DEBUGOUTINT( intval )
#define DEBUGOUTSZ( szval )
#endif

enum _MSGTYPE { INTERNERROR = -1, NOERROR = 0, SSLERROR = 1 };

struct _sslmsg_t
{
     char szErrorName[ 72 ];
     int nCertNmbr;
};

const char szMsgConcurrencyRequired[ ] = "This SSL Certificate Validator 
helper is concurrent and requires the concurrency option to be specified.";
const char szMsgInvalidSize[ ] = "SSL Certificate Validator: invalid 
request size parameter.";
const char szMsgMemoryAllocFailed[ ] = "SSL Certificate Validator: 
memory allocation failed.";
const char szMsgSyntaxError[ ] = "SSL Certificate Validator: request 
syntax error.";
const char szMsgReadIOError[ ] = "SSL Certificate Validator: read i/o 
error.";
const char szMsgUnknownError[ ] = "SSL Certificate Validator: unknown 
error.";

const char szSslMsgCertRevoked[ ] = "X509_V_ERR_CERT_REVOKED";
const char szSslMsgCertUntrusted[ ] = "X509_V_ERR_CERT_UNTRUSTED";

const char szSslMsgCertRejected[ ] = "X509_V_ERR_CERT_REJECTED";

const char szSslMsgCertHasExpired[ ] = "X509_V_ERR_CERT_HAS_EXPIRED";
const char szSslMsgCertNotYetValid[ ] = "X509_V_ERR_CERT_NOT_YET_VALID";

const char szSslMsgCertChainTooLong[ ] = "X509_V_ERR_CERT_CHAIN_TOO_LONG";

const char szSslMsgCertSelfSigned[ ] = 
"X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT";

const char szSslMsgCertSelfSignedInChain[ ] =
     "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN";

const char szSslMsgCertPathLengthExceeded[ ] = 
"X509_V_ERR_PATH_LENGTH_EXCEEDED";

const char szSslMsgInvalidCa[ ] = "X509_V_ERR_INVALID_CA";

const char szSslMsgSquidDomainMismatch[ ] = 
"SQUID_X509_V_ERR_DOMAIN_MISMATCH";

const char* pszSslMsgs[ ] = { szSslMsgSquidDomainMismatch,
     szSslMsgCertPathLengthExceeded,
     szSslMsgCertSelfSigned,
     szSslMsgCertSelfSignedInChain,
     szSslMsgCertUntrusted,
     szSslMsgCertRevoked,
     szSslMsgCertHasExpired, szSslMsgCertNotYetValid };

#ifdef _DEBUG
const char szDbgMarkInit[ ] = "=====[ INIT ]=====\n";
const char szDbgMarkReceiveRqustBegin[ ] = "-----[ REQUEST BEGIN ]-----\n";
const char szDbgMarkReceiveRqustEnd[ ] = "-----[ REQUEST END ]-----\n";
const char szDbgMarkReturnMsgBegin[ ] = "-----[ MSG BEGIN ]-----\n";
const char szDbgMarkReturnMsgEnd[ ] = "-----[ MSG END ]-----\n";
#endif


static int nFileCert;
static int nFileChain;
static int nFileIssuer;

static char szFnameCert[ 260 ];
static char szFnameChain[ 260 ];
static char szFnameIssuer[ 260 ];

static char szSslHost[ 260 ];

static char* pszRqustBuf = (char*) NULL;

static struct _sslmsg_t stRqustSslMsgs[ 8 ];
static int nRqustSslMsgsCount;


void cleanupData( void );

void initData( void );

int readRqustHlpr( int* pnEchoId, int* pnRqustRead );
int receiveRequest( int* pnEchoId );

void returnMsg( int nEchoId, int nMsgType, int nCert, const char* pszMsg );

int verifyCertificate( char* pszSslMsg );
int verifyHostName( const char* pszHostName );

#ifdef _DEBUG
void debugInit( int nLine );
void debugOutputHlpr( int nLine, const void* pvdBuf, int nBufLen );
void debugOutputInt( int nLine, const char* pszName, int nVal );
void debugOutputStr( int nLine, const char* pszName, const char* pszVal );
void debugWrite( const void* pvdBuf, int nBufLen );
#endif


// call params: none

int main( int argc, char* argv[ ] )
{
     int nEchoId, nRet = 0;

     DEBUGINIT( );

     initData( );

     nRet = receiveRequest( &nEchoId );

     DEBUGOUTINT( nRet );

     if ( nRet < 0 )
     {
         switch ( nRet )
         {
             case -1 :
                 returnMsg( -1, (int) INTERNERROR, -1, 
szMsgConcurrencyRequired );
                 break;
             case -2 :
                 returnMsg( 0, (int) INTERNERROR, -1, 
szMsgMemoryAllocFailed );
                 break;
             case -3 :
                 returnMsg( 0, (int) INTERNERROR, -1, szMsgInvalidSize );
                 break;
             case -4 :
                 returnMsg( 0, (int) INTERNERROR, -1, szMsgSyntaxError );
                 break;
             case -5 :
                 returnMsg( 0, (int) INTERNERROR, -1, szMsgReadIOError );
                 break;
             default :
                 returnMsg( 0, (int) INTERNERROR, -1, szMsgUnknownError );
         }
         cleanupData( );
         exit( EXIT_FAILURE );
     }

     if ( nRet > 0 )
     {
         returnMsg( nEchoId, (int) NOERROR, 0, (const char*) NULL );
         cleanupData( );
         exit( EXIT_SUCCESS );
     }

     {
         int m, n;
         for ( n = 0; n < sizeof( pszSslMsgs ) / sizeof( char* ); n++ )
             for ( m = 0; m < nRqustSslMsgsCount; m++ )
                 if ( strcmp( pszSslMsgs[ n ], stRqustSslMsgs[ m 
].szErrorName ) == 0 )
                 {
                     returnMsg( nEchoId, (int) SSLERROR,
                         stRqustSslMsgs[ m ].nCertNmbr,
                         stRqustSslMsgs[ m ].szErrorName );
                     cleanupData( );
                     exit( EXIT_SUCCESS );
                 }
     }

     if ( verifyHostName( szSslHost ) < 0 )
     {
         returnMsg( nEchoId, (int) SSLERROR, 0, 
szSslMsgSquidDomainMismatch );
         cleanupData( );
         exit( EXIT_SUCCESS );
     }

     {
         static char szSslMsg[ 72 ];
         if ( ( nRet = verifyCertificate( szSslMsg ) ) < 0 )
         {
             returnMsg( nEchoId, (int) INTERNERROR, -1, szMsgUnknownError );
             cleanupData( );
             exit( EXIT_FAILURE );
         }
         if ( nRet > 0 )
         {
             returnMsg( nEchoId, (int) SSLERROR, 0, szSslMsg );
             cleanupData( );
             exit( EXIT_SUCCESS );
         }
     }
     returnMsg( nEchoId, (int) NOERROR, 0, (const char*) NULL );
     cleanupData( );
     exit( EXIT_SUCCESS );

     return 0;
}

void cleanupData( void )
{
     if ( nFileCert > 0 )
     {
         unlink( szFnameCert );
         nFileCert = 0;
     }
     if ( nFileChain > 0 )
     {
         unlink( szFnameChain );
         nFileChain = 0;
     }
     if ( nFileIssuer > 0 )
     {
         unlink( szFnameIssuer );
         nFileIssuer = 0;
     }
     if ( pszRqustBuf )
     {
         free( pszRqustBuf );
         pszRqustBuf = (char*) NULL;
     }
     fsync( STDOUT_FILENO );
}

void initData( void )
{
     const char szFnameTmplte[ ] = "/tmp/squidXXXXXXXX";

     register int n;

     for ( n = 0; n < sizeof( stRqustSslMsgs ) / sizeof( struct 
_sslmsg_t ); n++ )
     {
         strcpy( stRqustSslMsgs[ n ].szErrorName, "" );
         stRqustSslMsgs[ n ].nCertNmbr = 0;
     }

     nRqustSslMsgsCount = 0;

     strcpy( szFnameCert, szFnameTmplte );
     strcpy( szFnameChain, szFnameTmplte );
     strcpy( szFnameIssuer, szFnameTmplte );

     nFileCert = nFileChain = nFileIssuer = 0;
}

int readRqustHlpr( int* pnEchoId, int* pnRqustRead )
{
     const char chLf = '\n';

     static szBuf[ 260 ];

     int nLen, nCount = 0, nSize = 0, nRet = 0;

     if ( ( nLen = read( STDIN_FILENO, (void*) szBuf, 256 ) ) > 0 )
     {
         char* pszNxt;

         szBuf[ nLen ] = '\0';

         DEBUGOUT( szDbgMarkReceiveRqustBegin );

         {
             char* psz = (char*) szBuf;
             long l = (long) strtol( psz, &pszNxt, 10 );
             if ( psz < pszNxt )
             {
                 *pnEchoId = (int) l;
             }
             else
             {
                 nRet = -1;
             }
         }

         if ( nRet >= 0 )
         {
             char* psz = (char*) ++pszNxt;

             DEBUGOUT2( szBuf, nLen );

             if ( strncmp( psz, "cert_validate", 13 ) == 0 )
             {
                 long lVal = (long) strtol( psz + 14, &pszNxt, 10 );
                 if ( ( lVal > 0L ) && ( lVal < 10000L ) )
                     nSize = (int) lVal;
                 else
                     *pnRqustRead = -1;

                 if ( nSize > 0 )
                 {
                     if ( pszRqustBuf = (char*) malloc( nSize + 4 ) )
                     {
                         int n = (int) strlen( ++pszNxt );

                         strcpy( pszRqustBuf, pszNxt );
                         while ( ( n < nSize ) && ( ( nLen = read( 
STDIN_FILENO, (void*) ( pszRqustBuf + n ), nSize - n ) ) > 0 ) )
                         {
                             *( pszRqustBuf + n + nLen ) = '\0';

                             DEBUGOUT2( pszRqustBuf + n, nLen );
                             nCount++;
                             n += nLen;
                         }
                         DEBUGOUT2( &chLf, 1 );

                         if ( n >= nSize )
                             *pnRqustRead = 1;
                         else
                             nRet = -5;
                     }
                     else
                         nRet = -2;
                 }
                 else
                     nRet = -3;
             }
             else
                 nRet = -4;
         }

         DEBUGOUT( szDbgMarkReceiveRqustEnd );
     }
     else
         nRet = -5;

     DEBUGOUTINT( nRet );
     DEBUGOUTINT( nSize );
     DEBUGOUTINT( nCount );

     return nRet;
}

int receiveRequest( int* pnEchoId )
{
     const char chLf = '\n';

     static char sz[ 130 ], szTmp[ 50 ];

     char* pszItemPtr;

     int m, n, nItemLen, nRqustRead = 0;

     int nRet = (int) readRqustHlpr( pnEchoId, &nRqustRead );

     DEBUGOUTINT( nRqustRead );

     if ( nRet < 0 )
         return nRet;

     if ( nRet == 0 )
     {
         if ( pszItemPtr = strstr( pszRqustBuf, "host=" ) )
         {
             nItemLen = strcspn( pszItemPtr += 5, " \r\n" );
             strncpy( szSslHost, pszItemPtr, nItemLen );
             szSslHost[ nItemLen ] = '\0';
         }
         else
             nRet = 1;
     }

     DEBUGOUTINT( nRet );

     if ( nRet > 0 )
         return nRet;

     DEBUGOUTSZ( szSslHost );

     if ( nRet == 0 )
     {
         for ( n = 0; n < 8; n++ )
         {
             int nCertNmbr = -1;

             sprintf( sz, "error_cert_%d=", n );
             if ( pszItemPtr = strstr( pszRqustBuf, sz ) )
             {
                 nItemLen = strcspn( pszItemPtr += 13, " \r\n" );
                 strncpy( szTmp, (void*) pszItemPtr, nItemLen );
                 szTmp[ nItemLen ] = '\0';

                 for ( m = 0; m < 7; m++ )
                 {
                     sprintf( sz, "cert_%d", m );
                     if ( strcmp( sz, szTmp ) == 0 )
                     {
                         nCertNmbr = m;
                         break;
                     }
                 }
             }
             if ( nCertNmbr >= 0 )
             {
                 sprintf( sz, "error_name_%d=", n );
                 if ( pszItemPtr = strstr( pszRqustBuf, sz ) )
                 {
                     nItemLen = strcspn( pszItemPtr += 13, " \r\n" );
                     strncpy( szTmp, (void*) pszItemPtr, nItemLen );
                     szTmp[ nItemLen ] = '\0';
                     strcpy( stRqustSslMsgs[ nRqustSslMsgsCount 
].szErrorName, szTmp );
                     stRqustSslMsgs[ nRqustSslMsgsCount++ ].nCertNmbr = 
nCertNmbr;
                 }
                 else
                     nRet = 1;
             }
         }
     }

     DEBUGOUTINT( nRet );

     if ( nRet > 0 )
         return nRet;

     DEBUGOUTINT( nRqustSslMsgsCount );
#ifdef _DEBUG
     for ( n = 0; n < nRqustSslMsgsCount; n++ )
     {
         DEBUGOUTINT( stRqustSslMsgs[ n ].nCertNmbr );
         DEBUGOUTSZ( stRqustSslMsgs[ n ].szErrorName );
     }
#endif

     if ( nRet == 0 )
     {
         if ( ( nFileCert = mkstemp( szFnameCert ) ) > 0 );
         else
         {
             nRet = 2;
         }
         if ( nRet == 0 )
         {
             if ( ( nFileChain = mkstemp( szFnameChain ) ) > 0 );
             else
             {
                 close( nFileCert );
                 unlink( szFnameCert );
                 nFileCert = 0;
                 nRet = 2;
             }
         }
         if ( nRet == 0 )
         {
             if ( ( nFileIssuer = mkstemp( szFnameIssuer ) ) > 0 );
             else
             {
                 close( nFileCert );
                 close( nFileChain );
                 unlink( szFnameCert );
                 unlink( szFnameChain );
                 nFileCert = 0;
                 nFileChain = 0;
                 nRet = 2;
             }
         }
     }

     DEBUGOUTINT( nRet );

     if ( nRet > 0 )
         return nRet;

     DEBUGOUTINT( nFileCert );
     DEBUGOUTINT( nFileChain );
     DEBUGOUTINT( nFileIssuer );

     if ( nRet == 0 )
     {
         for ( n = 0; n < 8; n++ )
         {
             sprintf( sz, "cert_%d=-----BEGIN CERTIFICATE-----", n );
             if ( pszItemPtr = strstr( pszRqustBuf, sz ) )
             {
                 char* pszTag = (char*) strstr( pszItemPtr += 7, 
"-----END CERTIFICATE-----" );
                 if ( pszTag )
                 {
                     nItemLen = (int) ( pszTag - pszItemPtr ) + 25;
                     if ( n == 0 )
                     {
                         write( nFileCert, (void*) pszItemPtr, nItemLen );
                         write( nFileCert, (void*) &chLf, 1 );
                     }
                     if ( n == 1 )
                     {
                         write( nFileIssuer, (void*) pszItemPtr, nItemLen );
                         write( nFileIssuer, (void*) &chLf, 1 );
                     }
                     if ( n >= 1 )
                     {
                         write( nFileChain, (void*) pszItemPtr, nItemLen );
                         write( nFileChain, (void*) &chLf, 1 );
                     }
                 }
                 else
                 {
                     nRet = 3;
                     break;
                 }
             }
             else
             {
                 if ( n == 0 )
                     nRet = 3;
                 break;
             }
         }

         close( nFileCert );
         close( nFileChain );
         close( nFileIssuer );
     }

     DEBUGOUTINT( nRet );

     DEBUGOUTSZ( szFnameCert );
     DEBUGOUTSZ( szFnameChain );
     DEBUGOUTSZ( szFnameIssuer );

     return nRet;
}

void returnMsg( int nEchoId, int nMsgType, int nCert, const char* pszMsg )
{
     static char sz[ 260 ];
     static char szMsgBuf[ 260 ];

#ifdef _DEBUG
     const char szEndTerm[ ] = "\\x01\n";
#endif

     if ( nMsgType == (int) NOERROR )
     {
         sprintf( szMsgBuf, "%d OK 0 \1", nEchoId );
     }
     else
     {
         if ( nMsgType == (int) SSLERROR )
         {
             const char szFmtError[ ] = "error_name_0=%s\n"
                 "error_reason_0=Checked by "
                     "Squid SSL Certificate Validator\n"
                 "error_cert_0=cert_%d\n";

             sprintf( sz, szFmtError, pszMsg, nCert );

             sprintf( szMsgBuf, "%d ERR %d %s\1", nEchoId,
                 strlen( sz ), sz );
         }
         else
         {
             const char szFmtMessage[ ] = "message=\"%s\"";

             sprintf( sz, szFmtMessage, pszMsg );

             if ( nEchoId >= 0 )
                 sprintf( szMsgBuf, "%d BH %s\1", nEchoId, sz );
             else
                 sprintf( szMsgBuf, "BH %s\1", sz );
         }
     }

     write( STDOUT_FILENO, (void*) szMsgBuf, strlen( szMsgBuf ) );

     DEBUGOUTINT( nMsgType );
     DEBUGOUTINT( nCert );

     DEBUGOUT( szDbgMarkReturnMsgBegin );
     DEBUGOUT2( szMsgBuf, strlen( szMsgBuf ) - 1 );
     DEBUGOUT2( szEndTerm, strlen( szEndTerm ) );
     DEBUGOUT( szDbgMarkReturnMsgEnd );
}

int verifyCertificate( char* pszSslMsg )
{
     static char szGrabStdOut[ 4100 ];
     static char szGrabStdErr[ 4100 ];

     int pipefdin[ 2 ];
     int pipefdout[ 2 ];
     int pipefderr[ 2 ];

     pid_t cpid;

     if ( pipe( pipefdin ) == -1 )
         goto failPipeIn;

     DEBUGOUTINT( pipefdin[ 0 ] );
     DEBUGOUTINT( pipefdin[ 1 ] );

     if ( pipe( pipefdout ) == -1 )
         goto failPipeOut;

     DEBUGOUTINT( pipefdout[ 0 ] );
     DEBUGOUTINT( pipefdout[ 1 ] );

     if ( pipe( pipefderr ) == -1 )
         goto failPipeErr;

     DEBUGOUTINT( pipefderr[ 0 ] );
     DEBUGOUTINT( pipefderr[ 1 ] );

     cpid = fork( );
     if ( cpid == -1 )
         goto failFork;

     DEBUGOUTINT( cpid );

     if ( cpid == 0 )
     {                /* inside child fork */
         close( pipefdin[ 1 ] );
         close( pipefdout[ 0 ] );
         close( pipefderr[ 0 ] );

         dup2( pipefdin[ 0 ], STDIN_FILENO );
         close( pipefdin[ 0 ] );

         dup2( pipefdout[ 1 ], STDOUT_FILENO );
         close( pipefdout[ 1 ] );

         dup2( pipefderr[ 1 ], STDERR_FILENO );
         close( pipefderr[ 1 ] );

         if ( execl( "/usr/lib64/squid/ssl_crtvalid/verify.sh", 
"./verify.sh",
             szFnameCert, szFnameIssuer, szFnameChain, szSslHost,
             (char*) NULL ) == -1 )
         {
             exit( EXIT_FAILURE );
         }
     }
     else
     {                /* inside parent fork */
         char* psz;
         int n;

         close( pipefdin[ 0 ] );
         close( pipefdout[ 1 ] );
         close( pipefderr[ 1 ] );

         close( pipefdin[ 1 ] );

         n = 0, psz = szGrabStdOut;
         while ( ( n++ < 4096 ) && ( read( pipefdout[ 0 ], psz++, 1 ) > 
0 ) )
             *psz = '\0';

         n = 0, psz = szGrabStdErr;
         while ( ( n++ < 4096 ) && ( read( pipefderr[ 0 ], psz++, 1 ) > 
0 ) )
             *psz = '\0';

         close( pipefdout[ 0 ] );
         close( pipefderr[ 0 ] );

         wait( NULL );
     }

     /* this is only parent fork */

     DEBUGOUTSZ( szGrabStdOut );
     DEBUGOUTSZ( szGrabStdErr );

     {
         static char sz[ 260 ];

         char* psz = (char*) szGrabStdOut;

         sprintf( sz, "%s: OK", szFnameCert );
         if ( strncmp( psz, sz, strlen( sz ) ) == 0 )
         {
             psz += strlen( sz ) + 1;

             sprintf( sz, "%s: revoked", szFnameCert );
             if ( strncmp( psz, sz, strlen( sz ) ) == 0 )
             {
                 strcpy( pszSslMsg, szSslMsgCertRevoked );
                 return 1;
             }

             sprintf( sz, "%s: good", szFnameCert );
             if ( strncmp( psz, sz, strlen( sz ) ) == 0 );
             else
                 goto invalidCert;
         }
         else
         {
invalidCert:
             strcpy( pszSslMsg, szSslMsgCertRejected );
             return 1;
         }
     }

     return 0;

failFork:
     close( pipefderr[ 0 ] );
     close( pipefderr[ 1 ] );
failPipeErr:
     close( pipefdout[ 0 ] );
     close( pipefdout[ 1 ] );
failPipeOut:
     close( pipefdin[ 0 ] );
     close( pipefdin[ 1 ] );
failPipeIn:
     return -1;
}

int verifyHostName( const char* pszHostName )
{
     int nLen = (int) strlen( pszHostName );
     char* psz = (char*) ( pszHostName + nLen - 1 );

     if ( strspn( pszHostName, "0123456789." ) == nLen )
         return -1;

     if ( strspn( pszHostName, "0123456789abcdefghijklmnopqrstuvwxyz.-" 
) < nLen )
         return -1;

     if ( *psz == ']' )
         return -1;

     if ( isdigit( (int) *psz ) )
         return -1;
}


#ifdef _DEBUG
void debugInit( int nLine )
{
     static char sz[ 260 ];

     time_t t = time( (time_t*) NULL );

     debugWrite( (const void*) szDbgMarkInit, strlen( szDbgMarkInit ) );

     strftime( sz, 80, "date/time: %a, %d-%b-%Y; %H:%M:%S\n", localtime( 
&t ) );
     debugOutputHlpr( nLine, (const void*) sz, strlen( sz ) );
}

void debugOutputHlpr( int nLine, const void* pvdBuf, int nBufLen )
{
     static char sz[ 130 ];

     pid_t pid = (pid_t) getpid( );

     sprintf( sz, "ssl_crtvalid/helper[pid=%d,line=%d] ", (int) pid, 
(int) nLine );

     debugWrite( (const void*) sz, strlen( sz ) );
     debugWrite( pvdBuf, nBufLen );
}

void debugOutputInt( int nLine, const char* pszName, int nVal )
{
     static char sz[ 260 ];
     sprintf( sz, "%s: %d\n", pszName, nVal );
     debugOutputHlpr( nLine, (const void*) sz, strlen( sz ) );
}

void debugOutputStr( int nLine, const char* pszName, const char* pszVal )
{
     static char sz[ 260 ];
     sprintf( sz, "%s: '%s'\n", pszName, pszVal );
     debugOutputHlpr( nLine, (const void*) sz, strlen( sz ) );
}

void debugWrite( const void* pvdBuf, int nBufLen )
{
     write( STDERR_FILENO, pvdBuf, nBufLen );
}
#endif
</helper.c>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squid-cache.org/pipermail/squid-users/attachments/20151018/2f4aa812/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4312 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.squid-cache.org/pipermail/squid-users/attachments/20151018/2f4aa812/attachment-0001.bin>


More information about the squid-users mailing list