Mixe for Privacy and Anonymity in the Internet
CATLSClientSocket.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000, The JAP-Team
00003 All rights reserved.
00004 Redistribution and use in source and binary forms, with or without modification,
00005 are permitted provided that the following conditions are met:
00006 
00007   - Redistributions of source code must retain the above copyright notice,
00008     this list of conditions and the following disclaimer.
00009 
00010   - Redistributions in binary form must reproduce the above copyright notice,
00011     this list of conditions and the following disclaimer in the documentation and/or
00012     other materials provided with the distribution.
00013 
00014   - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors
00015     may be used to endorse or promote products derived from this software without specific
00016     prior written permission.
00017 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00027 */
00028 #include "StdAfx.h"
00029 #ifndef ONLY_LOCAL_PROXY
00030 #ifdef PAYMENT
00031 #include "CATLSClientSocket.hpp"
00032 #include "CAUtil.hpp"
00033 #include "CAMsg.hpp"
00034 
00035 CATLSClientSocket::CATLSClientSocket()
00036   {
00037     m_bConnectedTLS = false;
00038     m_pCtx = SSL_CTX_new( TLSv1_client_method() );
00039 #ifdef SSL_OP_NO_TICKET
00040     // disable buggy TLS client extensions, as otherwise we will get no connection to a Java TLS server; the bug is fixes in OpenSSL > 0.9.8g
00041     SSL_CTX_set_options(m_pCtx, SSL_OP_ALL|SSL_OP_NO_TICKET);
00042 #else
00043     SSL_CTX_set_options(m_pCtx, SSL_OP_ALL);
00044 #endif
00045     m_pSSL = NULL;
00046     m_pRootCert=NULL;
00047     //m_pSocket=new CASocket();
00048 
00049   }
00050 
00051 CATLSClientSocket::~CATLSClientSocket()
00052   {
00053     close();
00054     SSL_CTX_free(m_pCtx);
00055     //delete m_pSocket;
00056     //m_pSocket = NULL;
00057     delete m_pRootCert;
00058     m_pRootCert = NULL;
00059   }
00060 
00065 SINT32 CATLSClientSocket::close()
00066   {
00067     if(m_bConnectedTLS)
00068       {
00069         SSL_shutdown(m_pSSL);
00070         m_bConnectedTLS = false;
00071       }
00072     if(m_pSSL!=NULL)
00073       {
00074         SSL_free(m_pSSL);
00075       }
00076     m_pSSL=NULL;
00077     return CASocket::close();
00078   }
00079 
00080 
00081 
00082 
00086 SINT32 CATLSClientSocket::setServerCertificate(CACertificate* pCert)
00087   {
00088     m_pRootCert=pCert->clone();
00089     return E_SUCCESS;
00090   }
00091 
00092 
00097 SINT32 CATLSClientSocket::doTLSConnect(CASocketAddr &psa)
00098   {
00099     SINT32 status;
00100     #ifdef DEBUG
00101       CAMsg::printMsg(LOG_DEBUG,"starting tls connect\n");
00102     #endif
00103     if(m_bConnectedTLS)
00104       return E_UNKNOWN;
00105 
00106     m_pSSL=SSL_new(m_pCtx);
00107     // do the standard part of the ssl handshake
00108     
00109     SSL_set_fd( m_pSSL, m_Socket );
00110     if((status = SSL_connect( m_pSSL )) != 1) 
00111     {
00112         int err = SSL_get_error(m_pSSL, status);
00113         CAMsg::printMsg(LOG_INFO,"CATLSClientSocket::doTLSConnect() failed! Reason: %i\n", err);
00114       SSL_shutdown(m_pSSL);
00115       close();
00116       m_bConnectedTLS = false;
00117       return E_UNKNOWN;
00118     }
00119     #ifdef DEBUG
00120       CAMsg::printMsg(LOG_DEBUG,"connect passed\n");
00121     #endif
00122 
00123     // ssl handshake ok, now let's check the server's identity
00124     // Note: This code was stolen from LinuxJournal
00125     // issue 89: An Introduction to OpenSSL Programming, Part I of II
00126 
00127 
00128     // is the certificate valid?
00129     SINT32 ret=SSL_get_verify_result( m_pSSL );
00130     if(ret != X509_V_OK&&ret!=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT )
00131       {
00132         CAMsg::printMsg(LOG_ERR, "SSLClientSocket: the Server certificate is INVALID!! Error: %i\n",ret);
00133         close();
00134         m_bConnectedTLS = false;
00135         return E_UNKNOWN;
00136       }
00137     X509* peerCert=SSL_get_peer_certificate(m_pSSL);
00138     if(peerCert==NULL)
00139       {
00140         CAMsg::printMsg(LOG_ERR, "SSLClientSocket: the Server shows no certificate!\n");
00141         close();
00142         m_bConnectedTLS = false;
00143         return E_UNKNOWN;
00144       }
00145     ret=1;
00146     if(m_pRootCert!=NULL)
00147       {
00148         EVP_PKEY* pubKey=X509_get_pubkey(m_pRootCert->getX509());
00149         ret=X509_verify(peerCert,pubKey);
00150       }
00151     X509_free(peerCert);
00152     if(ret!=1)
00153       {
00154         CAMsg::printMsg(LOG_ERR, "SSLClientSocket: could not verify server certificate!\n");
00155         close();
00156         m_bConnectedTLS = false;
00157         return E_UNKNOWN;
00158       }
00159     m_bConnectedTLS = true;
00160     return E_SUCCESS;
00161   }
00162 
00163 
00164 
00165 
00170 SINT32 CATLSClientSocket::connect(CASocketAddr & psa, UINT32 msTimeout)
00171   {
00172     SINT32 rc;
00173     // call base class connect function
00174     if( (rc=CASocket::connect(psa, msTimeout)) != E_SUCCESS)
00175     {
00176       CASocket::close();
00177       return rc;
00178     }
00179     // do our own connection initialisation (TLS handshake)
00180     rc = doTLSConnect(psa);
00181     return rc;
00182   }
00183 
00190 SINT32 CATLSClientSocket::send(const UINT8* buff,UINT32 len)
00191 {
00192   if(len==0)
00193   {
00194     return E_SUCCESS; //nothing to send
00195   }
00196   SINT32 ret=::SSL_write(m_pSSL,(char*)buff,len);
00197   if(ret<0)
00198   {
00199       int err = SSL_get_error(m_pSSL, ret);
00200     if ( (SSL_ERROR_WANT_READ == err) ||
00201        (SSL_ERROR_WANT_WRITE == err) )
00202       {
00203         return E_AGAIN;
00204       }
00205 
00206     if( (err == SSL_ERROR_SYSCALL) && (ret == -1) )
00207     {
00208       int errnum = errno;
00209       CAMsg::printMsg(LOG_ERR, "TLS-Socket: send I/O error occured: %s\n", strerror(errnum));
00210     }
00211     return SOCKET_ERROR;
00212   }
00213   return ret;
00214 }
00215 
00222 SINT32 CATLSClientSocket::sendFully(const UINT8* buff, UINT32 len)
00223   {
00224     if(len==0)
00225       return E_SUCCESS; //nothing to send
00226     SINT32 ret=::SSL_write(m_pSSL,(char*)buff,len);
00227     if(ret < 0 || ret < len)
00228       return E_UNKNOWN;
00229     return E_SUCCESS;
00230   }
00231 
00232 
00244 SINT32 CATLSClientSocket::receive(UINT8* buff,UINT32 len)
00245 {
00246   SINT32 ret=::SSL_read(m_pSSL,(char*)buff,len);
00247   if(ret<0)
00248     {
00249       int err = SSL_get_error(m_pSSL, ret);
00250     if ( (SSL_ERROR_WANT_READ == err) ||
00251        (SSL_ERROR_WANT_WRITE == err) )
00252       {
00253         return E_AGAIN;
00254       }
00255 
00256     if( (err == SSL_ERROR_SYSCALL) && (ret == -1) )
00257     {
00258       int errnum = errno;
00259       CAMsg::printMsg(LOG_ERR, "TLS-Socket: receive I/O error occured: %s\n", strerror(errnum));
00260     }
00261     return SOCKET_ERROR;
00262     }
00263   return ret;
00264 }
00265 
00266 #endif
00267 #endif //ONLY_LOCAL_PROXY