📄 pssl.cxx
字号:
{
return SSL_CTX_use_certificate(context, certificate) > 0;
}
BOOL PSSLContext::UsePrivateKey(const PSSLPrivateKey & key)
{
if (SSL_CTX_use_PrivateKey(context, key) <= 0)
return FALSE;
return SSL_CTX_check_private_key(context);
}
BOOL PSSLContext::UseDiffieHellman(const PSSLDiffieHellman & dh)
{
return SSL_CTX_set_tmp_dh(context, (dh_st *)dh) > 0;
}
BOOL PSSLContext::SetCipherList(const PString & ciphers)
{
if (ciphers.IsEmpty())
return FALSE;
return SSL_CTX_set_cipher_list(context, (char *)(const char *)ciphers);
}
/////////////////////////////////////////////////////////////////////////
//
// SSLChannel
//
PSSLChannel::PSSLChannel(PSSLContext * ctx, BOOL autoDel)
{
if (ctx != NULL) {
context = ctx;
autoDeleteContext = autoDel;
}
else {
context = new PSSLContext;
autoDeleteContext = TRUE;
}
ssl = SSL_new(*context);
if (ssl == NULL)
PSSLAssert("Error creating channel: ");
}
PSSLChannel::PSSLChannel(PSSLContext & ctx)
{
context = &ctx;
autoDeleteContext = FALSE;
ssl = SSL_new(*context);
}
PSSLChannel::~PSSLChannel()
{
// free the SSL connection
if (ssl != NULL)
SSL_free(ssl);
if (autoDeleteContext)
delete context;
}
BOOL PSSLChannel::Read(void * buf, PINDEX len)
{
flush();
channelPointerMutex.StartRead();
lastReadCount = 0;
BOOL returnValue = FALSE;
if (readChannel == NULL)
SetErrorValues(NotOpen, EBADF, LastReadError);
else if (readTimeout == 0 && SSL_pending(ssl) == 0)
SetErrorValues(Timeout, ETIMEDOUT, LastReadError);
else {
readChannel->SetReadTimeout(readTimeout);
int readResult = SSL_read(ssl, (char *)buf, len);
lastReadCount = readResult;
returnValue = readResult > 0;
if (readResult < 0 && GetErrorCode(LastReadError) == NoError)
ConvertOSError(-1, LastReadError);
}
channelPointerMutex.EndRead();
return returnValue;
}
BOOL PSSLChannel::Write(const void * buf, PINDEX len)
{
flush();
channelPointerMutex.StartRead();
lastWriteCount = 0;
BOOL returnValue;
if (writeChannel == NULL) {
SetErrorValues(NotOpen, EBADF, LastWriteError);
returnValue = FALSE;
}
else {
writeChannel->SetWriteTimeout(writeTimeout);
int writeResult = SSL_write(ssl, (const char *)buf, len);
lastWriteCount = writeResult;
returnValue = lastWriteCount >= len;
if (writeResult < 0 && GetErrorCode(LastWriteError) == NoError)
ConvertOSError(-1, LastWriteError);
}
channelPointerMutex.EndRead();
return returnValue;
}
BOOL PSSLChannel::Close()
{
BOOL ok = SSL_shutdown(ssl);
return PIndirectChannel::Close() && ok;
}
BOOL PSSLChannel::ConvertOSError(int error, ErrorGroup group)
{
Errors lastError = NoError;
DWORD osError = 0;
if (SSL_get_error(ssl, error) != SSL_ERROR_NONE && (osError = ERR_peek_error()) != 0) {
osError |= 0x80000000;
lastError = Miscellaneous;
}
return SetErrorValues(lastError, osError, group);
}
PString PSSLChannel::GetErrorText(ErrorGroup group) const
{
if ((lastErrorNumber[group]&0x80000000) == 0)
return PIndirectChannel::GetErrorText(group);
char buf[200];
return ERR_error_string(lastErrorNumber[group]&0x7fffffff, buf);
}
BOOL PSSLChannel::Accept()
{
if (IsOpen())
return ConvertOSError(SSL_accept(ssl));
return FALSE;
}
BOOL PSSLChannel::Accept(PChannel & channel)
{
if (Open(channel))
return ConvertOSError(SSL_accept(ssl));
return FALSE;
}
BOOL PSSLChannel::Accept(PChannel * channel, BOOL autoDelete)
{
if (Open(channel, autoDelete))
return ConvertOSError(SSL_accept(ssl));
return FALSE;
}
BOOL PSSLChannel::Connect()
{
if (IsOpen())
return ConvertOSError(SSL_connect(ssl));
return FALSE;
}
BOOL PSSLChannel::Connect(PChannel & channel)
{
if (Open(channel))
return ConvertOSError(SSL_connect(ssl));
return FALSE;
}
BOOL PSSLChannel::Connect(PChannel * channel, BOOL autoDelete)
{
if (Open(channel, autoDelete))
return ConvertOSError(SSL_connect(ssl));
return FALSE;
}
BOOL PSSLChannel::UseCertificate(const PSSLCertificate & certificate)
{
return SSL_use_certificate(ssl, certificate);
}
void PSSLChannel::SetVerifyMode(VerifyMode mode)
{
int verify;
switch (mode) {
default :
case VerifyNone:
verify = SSL_VERIFY_NONE;
break;
case VerifyPeer:
verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
break;
case VerifyPeerMandatory:
verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
SSL_set_verify(ssl, verify, VerifyCallBack);
}
BOOL PSSLChannel::RawSSLRead(void * buf, PINDEX & len)
{
if (!PIndirectChannel::Read(buf, len))
return FALSE;
len = GetLastReadCount();
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
//
// Low level interface to SSLEay routines
//
#define PSSLCHANNEL(bio) ((PSSLChannel *)(bio->ptr))
extern "C" {
#if (OPENSSL_VERSION_NUMBER < 0x00906000)
typedef int (*ifptr)();
typedef long (*lfptr)();
#endif
static int Psock_new(BIO * bio)
{
bio->init = 0;
bio->num = 0;
bio->ptr = NULL; // this is really (PSSLChannel *)
bio->flags = 0;
return(1);
}
static int Psock_free(BIO * bio)
{
if (bio == NULL)
return 0;
if (bio->shutdown) {
if (bio->init) {
PSSLCHANNEL(bio)->Shutdown(PSocket::ShutdownReadAndWrite);
PSSLCHANNEL(bio)->Close();
}
bio->init = 0;
bio->flags = 0;
}
return 1;
}
static long Psock_ctrl(BIO * bio, int cmd, long num, void * /*ptr*/)
{
switch (cmd) {
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
return 1;
case BIO_CTRL_GET_CLOSE:
return bio->shutdown;
case BIO_CTRL_FLUSH:
return 1;
}
// Other BIO commands, return 0
return 0;
}
static int Psock_read(BIO * bio, char * out, int outl)
{
if (out == NULL)
return 0;
BIO_clear_retry_flags(bio);
// Skip over the polymorphic read, want to do real one
PINDEX len = outl;
if (PSSLCHANNEL(bio)->RawSSLRead(out, len))
return len;
switch (PSSLCHANNEL(bio)->GetErrorCode(PChannel::LastReadError)) {
case PChannel::Interrupted :
case PChannel::Timeout :
BIO_set_retry_read(bio);
return -1;
default :
break;
}
return 0;
}
static int Psock_write(BIO * bio, const char * in, int inl)
{
if (in == NULL)
return 0;
BIO_clear_retry_flags(bio);
// Skip over the polymorphic write, want to do real one
if (PSSLCHANNEL(bio)->PIndirectChannel::Write(in, inl))
return PSSLCHANNEL(bio)->GetLastWriteCount();
switch (PSSLCHANNEL(bio)->GetErrorCode(PChannel::LastWriteError)) {
case PChannel::Interrupted :
case PChannel::Timeout :
BIO_set_retry_write(bio);
return -1;
default :
break;
}
return 0;
}
static int Psock_puts(BIO * bio, const char * str)
{
int n,ret;
n = strlen(str);
ret = Psock_write(bio,str,n);
return ret;
}
};
static BIO_METHOD methods_Psock =
{
BIO_TYPE_SOCKET,
"PTLib-PSSLChannel",
#if (OPENSSL_VERSION_NUMBER < 0x00906000)
(ifptr)Psock_write,
(ifptr)Psock_read,
(ifptr)Psock_puts,
NULL,
(lfptr)Psock_ctrl,
(ifptr)Psock_new,
(ifptr)Psock_free
#else
Psock_write,
Psock_read,
Psock_puts,
NULL,
Psock_ctrl,
Psock_new,
Psock_free
#endif
};
BOOL PSSLChannel::OnOpen()
{
BIO * bio = BIO_new(&methods_Psock);
if (bio == NULL) {
SSLerr(SSL_F_SSL_SET_FD,ERR_R_BUF_LIB);
return FALSE;
}
// "Open" then bio
bio->ptr = this;
bio->init = 1;
SSL_set_bio(ssl, bio, bio);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
//
// misc unused code
//
#if 0
extern "C" {
static verify_depth = 0;
static verify_error = VERIFY_OK;
// should be X509 * but we can just have them as char *.
int verify_callback(int ok, X509 * xs, X509 * xi, int depth, int error)
{
char *s;
s = (char *)X509_NAME_oneline(X509_get_subject_name(xs));
if (s == NULL) {
// ERR_print_errors(bio_err);
return(0);
}
PError << "depth= " << depth << " " << (char *)s << endl;
free(s);
if (error == VERIFY_ERR_UNABLE_TO_GET_ISSUER) {
s=(char *)X509_NAME_oneline(X509_get_issuer_name(xs));
if (s == NULL) {
PError << "verify error" << endl;
//ERR_print_errors(bio_err);
return(0);
}
PError << "issuer = " << s << endl;
free(s);
}
if (!ok) {
PError << "verify error:num=" << error << " " <<
X509_cert_verify_error_string(error) << endl;
if (verify_depth <= depth) {
ok=1;
verify_error=VERIFY_OK;
} else {
ok=0;
verify_error=error;
}
}
PError << "verify return:" << ok << endl;
return(ok);
}
};
#endif
#endif // P_SSL
// End of file ////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -