mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
208 lines
4.1 KiB
C++
208 lines
4.1 KiB
C++
#include "SSL.h"
|
|
|
|
namespace Upp {
|
|
|
|
String SslBuffer::Get() const
|
|
{
|
|
if(IsEmpty())
|
|
return String::GetVoid();
|
|
return String(buf_mem->data, (int)buf_mem->length);
|
|
}
|
|
|
|
bool SslBuffer::Grow(int length)
|
|
{
|
|
return !IsEmpty() && BUF_MEM_grow(buf_mem, length);
|
|
}
|
|
|
|
bool SslBuffer::Set(const String& d)
|
|
{
|
|
if(!buf_mem && !Create())
|
|
return false;
|
|
int len = d.GetLength();
|
|
if((int)buf_mem->max < len && !Grow(len))
|
|
return false;
|
|
ASSERT((int)buf_mem->max >= len);
|
|
buf_mem->length = len;
|
|
memcpy(buf_mem, d, len);
|
|
return true;
|
|
}
|
|
|
|
bool SslStream::OpenBuffer(const char *data, int length)
|
|
{
|
|
return Set(BIO_new_mem_buf(const_cast<char *>(data), length));
|
|
}
|
|
|
|
bool SslStream::CreateBuffer()
|
|
{
|
|
Clear();
|
|
SslBuffer buf;
|
|
if(!buf.Create() || !Create(BIO_s_mem()))
|
|
return false;
|
|
BIO_set_mem_buf(bio, buf.Detach(), BIO_CLOSE);
|
|
return true;
|
|
}
|
|
|
|
String SslStream::GetResult() const
|
|
{
|
|
if(IsEmpty())
|
|
return String::GetVoid();
|
|
BUF_MEM *bm = NULL;
|
|
BIO_get_mem_ptr(bio, &bm);
|
|
if(!bm)
|
|
return String::GetVoid();
|
|
return String(bm->data, (int)bm->length);
|
|
}
|
|
|
|
bool SslKey::Load(const String& data)
|
|
{
|
|
Clear();
|
|
SslStream strm;
|
|
if(!strm.OpenBuffer(data.Begin(), data.GetLength()))
|
|
return false;
|
|
return Set(PEM_read_bio_PrivateKey(strm, NULL, NULL, NULL));
|
|
}
|
|
|
|
bool SslCertificate::Load(const String& data, bool asn1)
|
|
{
|
|
Clear();
|
|
SslStream in, pem, *sio = ∈
|
|
if(!in.OpenBuffer(data, data.GetLength()))
|
|
return false;
|
|
if(!asn1)
|
|
{
|
|
if(!pem.Create(BIO_f_base64()))
|
|
return false;
|
|
BIO_push(pem, in);
|
|
sio = &pem;
|
|
}
|
|
return Set(d2i_X509_bio(*sio, NULL));
|
|
}
|
|
|
|
String SslCertificate::Save(bool asn1) const
|
|
{
|
|
if(IsEmpty())
|
|
return String::GetVoid();
|
|
SslStream out, pem, *sio = &out;
|
|
if(!out.CreateBuffer())
|
|
return String::GetVoid();
|
|
if(!asn1)
|
|
{
|
|
if(!pem.Create(BIO_f_base64()))
|
|
return String::GetVoid();
|
|
BIO_push(pem, out);
|
|
sio = &pem;
|
|
}
|
|
i2d_X509_bio(*sio, cert);
|
|
return out.GetResult();
|
|
}
|
|
|
|
String SslCertificate::GetSubjectName() const
|
|
{
|
|
ASSERT(!IsEmpty());
|
|
return SslToString(X509_get_subject_name(cert));
|
|
}
|
|
|
|
String SslCertificate::GetIssuerName() const
|
|
{
|
|
ASSERT(!IsEmpty());
|
|
return SslToString(X509_get_issuer_name(cert));
|
|
}
|
|
|
|
Date SslCertificate::GetNotBefore() const
|
|
{
|
|
ASSERT(!IsEmpty());
|
|
return Asn1ToDate(X509_get_notBefore(cert));
|
|
}
|
|
|
|
Date SslCertificate::GetNotAfter() const
|
|
{
|
|
ASSERT(!IsEmpty());
|
|
return Asn1ToDate(X509_get_notAfter(cert));
|
|
}
|
|
|
|
int SslCertificate::GetVersion() const
|
|
{
|
|
ASSERT(!IsEmpty());
|
|
return X509_get_version(cert);
|
|
}
|
|
|
|
String SslCertificate::GetSerialNumber() const
|
|
{
|
|
ASSERT(!IsEmpty());
|
|
return Asn1ToString(X509_get_serialNumber(cert));
|
|
}
|
|
|
|
SslContext::SslContext(SSL_CTX *c)
|
|
: ssl_ctx(c)
|
|
{
|
|
SslInitThread();
|
|
}
|
|
|
|
bool SslContext::CipherList(const char *list)
|
|
{
|
|
ASSERT(ssl_ctx);
|
|
return SSL_CTX_set_cipher_list(ssl_ctx, list);
|
|
}
|
|
|
|
bool SslContext::UseCertificate(String certdata, String pkeydata, bool cert_asn1)
|
|
{
|
|
ASSERT(ssl_ctx);
|
|
if(IsNull(certdata) || IsNull(pkeydata))
|
|
return false;
|
|
SslCertificate cert;
|
|
SslKey pkey;
|
|
if(!cert.Load(certdata, cert_asn1) || !pkey.Load(pkeydata))
|
|
return false;
|
|
if(!SSL_CTX_use_certificate(ssl_ctx, cert) || !SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
|
|
return false;
|
|
if(!SSL_CTX_check_private_key(ssl_ctx))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void SslContext::VerifyPeer(bool verify, int depth)
|
|
{
|
|
ASSERT(ssl_ctx);
|
|
SSL_CTX_set_verify(ssl_ctx, verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
|
SSL_CTX_set_verify_depth(ssl_ctx, depth);
|
|
}
|
|
|
|
String SslGetLastError(int& code)
|
|
{
|
|
char errbuf[150];
|
|
ERR_error_string(code = ERR_get_error(), errbuf);
|
|
return errbuf;
|
|
}
|
|
|
|
String SslGetLastError()
|
|
{
|
|
int dummy;
|
|
return SslGetLastError(dummy);
|
|
}
|
|
|
|
String SslToString(X509_NAME *name)
|
|
{
|
|
char buffer[500];
|
|
return X509_NAME_oneline(name, buffer, sizeof(buffer));
|
|
}
|
|
|
|
Date Asn1ToDate(ASN1_STRING *time)
|
|
{
|
|
if(!time) return Null;
|
|
int digit = 0;
|
|
while(digit < time->length && IsDigit(time->data[digit]))
|
|
digit++;
|
|
if(digit < 6)
|
|
return Null;
|
|
int year2 = time->data[0] * 10 + time->data[1] - 11 * '0';
|
|
int month = time->data[2] * 10 + time->data[3] - 11 * '0';
|
|
int day = time->data[4] * 10 + time->data[5] - 11 * '0';
|
|
return Date(year2 + (year2 < 90 ? 2000 : 1900), month, day);
|
|
}
|
|
|
|
String Asn1ToString(ASN1_STRING *s)
|
|
{
|
|
return String(s->data, s->length);
|
|
}
|
|
|
|
}
|