📄 tlsconnection.cxx
字号:
}
if (bytesRead <= 0)
{
int err = SSL_get_error(mSsl,bytesRead);
switch (err)
{
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_NONE:
{
StackLog( << "Got TLS read got condition of " << err );
return 0;
}
break;
default:
{
char buf[256];
ERR_error_string_n(err,buf,sizeof(buf));
ErrLog( << "Got TLS read ret=" << bytesRead << " error=" << err << " " << buf );
return -1;
}
break;
}
assert(0);
}
StackLog(<<"SSL bytesRead="<<bytesRead);
return bytesRead;
#endif // USE_SSL
return -1;
}
int
TlsConnection::write( const char* buf, int count )
{
#if defined(USE_SSL)
assert( mSsl );
assert( buf );
int ret;
switch(checkState())
{
case Broken:
return -1;
break;
case Up:
break;
default:
return 0;
break;
}
if (!mBio)
{
DebugLog( << "Got TLS write bad bio " );
return 0;
}
ret = SSL_write(mSsl,(const char*)buf,count);
if (ret < 0 )
{
int err = SSL_get_error(mSsl,ret);
switch (err)
{
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_NONE:
{
StackLog( << "Got TLS write got condition of " << err );
return 0;
}
break;
default:
{
while (true)
{
const char* file;
int line;
unsigned long code = ERR_get_error_line(&file,&line);
if ( code == 0 )
{
break;
}
char buf[256];
ERR_error_string_n(code,buf,sizeof(buf));
ErrLog( << buf );
DebugLog( << "Error code = " << code << " file=" << file << " line=" << line );
}
ErrLog( << "Got TLS write error=" << err << " ret=" << ret );
return -1;
}
break;
}
}
Data monkey(Data::Borrow, buf, count);
StackLog( << "Did TLS write " << ret << " " << count << " " << "[[" << monkey << "]]" );
return ret;
#endif // USE_SSL
return -1;
}
bool
TlsConnection::hasDataToRead() // has data that can be read
{
#if defined(USE_SSL)
if (checkState() != Up)
{
return false;
}
int p = SSL_pending(mSsl);
//DebugLog(<<"hasDataToRead(): " <<p);
return (p>0);
#else // USE_SSL
return false;
#endif
}
bool
TlsConnection::isGood() // has data that can be read
{
#if defined(USE_SSL)
if ( mBio == 0 )
{
return false;
}
int mode = SSL_get_shutdown(mSsl);
if ( mode != 0 )
{
return false;
}
#endif
return true;
}
const std::list<Data>&
TlsConnection::getPeerNames() const
{
return mPeerNames;
}
Data
TlsConnection::getPeerNamesData() const
{
Data peerNamesString;
for(std::list<Data>::const_iterator it = mPeerNames.begin(); it != mPeerNames.end(); it++)
{
if(it == mPeerNames.begin())
{
peerNamesString += *it;
}
else
{
peerNamesString += ", " + *it;
}
}
return peerNamesString;
}
void
TlsConnection::computePeerName()
{
#if defined(USE_SSL)
Data commonName;
assert(mSsl);
if (!mBio)
{
ErrLog( << "bad bio" );
return;
}
// print session infor
SSL_CIPHER *ciph;
ciph=SSL_get_current_cipher(mSsl);
InfoLog( << "TLS sessions set up with "
<< SSL_get_version(mSsl) << " "
<< SSL_CIPHER_get_version(ciph) << " "
<< SSL_CIPHER_get_name(ciph) << " " );
// get the certificate if other side has one
X509* cert = SSL_get_peer_certificate(mSsl);
if ( !cert )
{
DebugLog(<< "No peer certificate in TLS connection" );
return;
}
// check that this certificate is valid
if (X509_V_OK != SSL_get_verify_result(mSsl))
{
DebugLog(<< "Peer certificate in TLS connection is not valid" );
X509_free(cert); cert=NULL;
return;
}
// look at the Common Name to find the peerName of the cert
X509_NAME* subject = X509_get_subject_name(cert);
assert(subject);
int i =-1;
while( true )
{
i = X509_NAME_get_index_by_NID(subject, NID_commonName,i);
if ( i == -1 )
{
break;
}
assert( i != -1 );
X509_NAME_ENTRY* entry = X509_NAME_get_entry(subject,i);
assert( entry );
ASN1_STRING* s = X509_NAME_ENTRY_get_data(entry);
assert( s );
int t = M_ASN1_STRING_type(s);
int l = M_ASN1_STRING_length(s);
unsigned char* d = M_ASN1_STRING_data(s);
Data name(d,l);
DebugLog( << "got x509 string type=" << t << " len="<< l << " data=" << d );
assert( name.size() == (unsigned)l );
DebugLog( << "Found common name in cert of " << name );
commonName = name;
}
#if 0 // junk code to print certificates extentions for debugging
int numExt = X509_get_ext_count(cert);
ErrLog(<< "Got peer certificate with " << numExt << " extentions" );
for ( int i=0; i<numExt; i++ )
{
X509_EXTENSION* ext = X509_get_ext(cert,i);
assert( ext );
const char* str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
assert(str);
DebugLog(<< "Got certificate extention" << str );
if ( OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_subject_alt_name )
{
DebugLog(<< "Got subjectAltName extention" );
}
}
#endif
// Look at the SubjectAltName, and if found, set as peerName
GENERAL_NAMES* gens;
gens = (GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
for(int i = 0; i < sk_GENERAL_NAME_num(gens); i++)
{
GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);
DebugLog(<< "subjectAltName of cert contains type <" << gen->type << ">" );
if (gen->type == GEN_DNS)
{
ASN1_IA5STRING* uri = gen->d.uniformResourceIdentifier;
int l = uri->length;
unsigned char* dat = uri->data;
Data name(dat,l);
InfoLog(<< "subjectAltName of TLS session cert contains <" << name << ">" );
mPeerNames.push_back(name);
}
if (gen->type == GEN_EMAIL)
{
DebugLog(<< "subjectAltName of cert has EMAIL type" );
}
if(gen->type == GEN_URI)
{
DebugLog(<< "subjectAltName of cert has GEN_URI type" );
}
}
sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
// If there are no peer names from the subjectAltName, then use the commonName
if(mPeerNames.empty())
{
mPeerNames.push_back(commonName);
}
// add the certificate to the Security store
unsigned char* buf = NULL;
int len = i2d_X509( cert, &buf );
Data derCert( buf, len );
for(std::list<Data>::iterator it = mPeerNames.begin(); it != mPeerNames.end(); it++)
{
if ( !mSecurity->hasDomainCert( *it ) )
{
mSecurity->addDomainCertDER(*it,derCert);
}
}
OPENSSL_free(buf); buf=NULL;
X509_free(cert); cert=NULL;
#endif // USE_SSL
}
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000-2005 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -