📄 pssl.cxx
字号:
PSSLCertificate::PSSLCertificate(const PFilePath & certFile, PSSLFileTypes fileType){ certificate = NULL; Load(certFile, fileType);}PSSLCertificate::PSSLCertificate(const BYTE * certData, PINDEX certSize){ certificate = d2i_X509(NULL, (unsigned char **)&certData, certSize);}PSSLCertificate::PSSLCertificate(const PBYTEArray & certData){ const BYTE * certPtr = certData; certificate = d2i_X509(NULL, (unsigned char **)&certPtr, certData.GetSize());}PSSLCertificate::PSSLCertificate(const PString & certStr){ PBYTEArray certData; PBase64::Decode(certStr, certData); if (certData.GetSize() > 0) { const BYTE * certPtr = certData; certificate = d2i_X509(NULL, (unsigned char **)&certPtr, certData.GetSize()); } else certificate = NULL;}PSSLCertificate::PSSLCertificate(const PSSLCertificate & cert){ if (cert.certificate == NULL) certificate = NULL; else certificate = X509_dup(cert.certificate);}PSSLCertificate & PSSLCertificate::operator=(const PSSLCertificate & cert){ if (certificate != NULL) X509_free(certificate); if (cert.certificate == NULL) certificate = NULL; else certificate = X509_dup(cert.certificate); return *this;}PSSLCertificate::~PSSLCertificate(){ if (certificate != NULL) X509_free(certificate);}BOOL PSSLCertificate::CreateRoot(const PString & subject, const PSSLPrivateKey & privateKey){ if (certificate != NULL) { X509_free(certificate); certificate = NULL; } if (privateKey == NULL) return FALSE; POrdinalToString info; PStringArray fields = subject.Tokenise('/', FALSE); PINDEX i; for (i = 0; i < fields.GetSize(); i++) { PString field = fields[i]; PINDEX equals = field.Find('='); if (equals != P_MAX_INDEX) { int nid = OBJ_txt2nid((char *)(const char *)field.Left(equals)); if (nid != NID_undef) info.SetAt(nid, field.Mid(equals+1)); } } if (info.IsEmpty()) return FALSE; certificate = X509_new(); if (certificate == NULL) return FALSE; if (X509_set_version(certificate, 2)) { /* Set version to V3 */ ASN1_INTEGER_set(X509_get_serialNumber(certificate), 0L); X509_NAME * name = X509_NAME_new(); for (i = 0; i < info.GetSize(); i++) X509_NAME_add_entry_by_NID(name, info.GetKeyAt(i), MBSTRING_ASC, (unsigned char *)(const char *)info.GetDataAt(i), -1,-1, 0); X509_set_issuer_name(certificate, name); X509_set_subject_name(certificate, name); X509_NAME_free(name); X509_gmtime_adj(X509_get_notBefore(certificate), 0); X509_gmtime_adj(X509_get_notAfter(certificate), (long)60*60*24*365*5); X509_PUBKEY * pubkey = X509_PUBKEY_new(); if (pubkey != NULL) { X509_PUBKEY_set(&pubkey, privateKey); EVP_PKEY * pkey = X509_PUBKEY_get(pubkey); X509_set_pubkey(certificate, pkey); EVP_PKEY_free(pkey); X509_PUBKEY_free(pubkey); if (X509_sign(certificate, privateKey, EVP_md5()) > 0) return TRUE; } } X509_free(certificate); certificate = NULL; return FALSE;}PBYTEArray PSSLCertificate::GetData() const{ PBYTEArray data; if (certificate != NULL) { BYTE * certPtr = data.GetPointer(i2d_X509(certificate, NULL)); i2d_X509(certificate, &certPtr); } return data;}PString PSSLCertificate::AsString() const{ return PBase64::Encode(GetData());}BOOL PSSLCertificate::Load(const PFilePath & certFile, PSSLFileTypes fileType){ if (certificate != NULL) { X509_free(certificate); certificate = NULL; } PSSL_BIO in; if (!in.OpenRead(certFile)) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB); return FALSE; } if (fileType == PSSLFileTypeDEFAULT) fileType = certFile.GetType() == ".pem" ? PSSLFileTypePEM : PSSLFileTypeASN1; switch (fileType) { case PSSLFileTypeASN1 : certificate = d2i_X509_bio(in, NULL); if (certificate != NULL) return TRUE; SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB); break; case PSSLFileTypePEM : certificate = PEM_read_bio_X509(in, NULL, NULL, NULL); if (certificate != NULL) return TRUE; SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_PEM_LIB); break; default : SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE); } return FALSE;}BOOL PSSLCertificate::Save(const PFilePath & certFile, BOOL append, PSSLFileTypes fileType){ if (certificate == NULL) return FALSE; PSSL_BIO out; if (!(append ? out.OpenAppend(certFile) : out.OpenWrite(certFile))) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB); return FALSE; } if (fileType == PSSLFileTypeDEFAULT) fileType = certFile.GetType() == ".pem" ? PSSLFileTypePEM : PSSLFileTypeASN1; switch (fileType) { case PSSLFileTypeASN1 : if (i2d_X509_bio(out, certificate)) return TRUE; SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB); break; case PSSLFileTypePEM : if (PEM_write_bio_X509(out, certificate)) return TRUE; SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_PEM_LIB); break; default : SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE); } return FALSE;}///////////////////////////////////////////////////////////////////////////////PSSLDiffieHellman::PSSLDiffieHellman(){ dh = NULL;}PSSLDiffieHellman::PSSLDiffieHellman(const PFilePath & dhFile, PSSLFileTypes fileType){ dh = NULL; Load(dhFile, fileType);}PSSLDiffieHellman::PSSLDiffieHellman(const BYTE * pData, PINDEX pSize, const BYTE * gData, PINDEX gSize){ dh = DH_new(); if (dh == NULL) return; dh->p = BN_bin2bn(pData, pSize, NULL); dh->g = BN_bin2bn(gData, gSize, NULL); if (dh->p != NULL && dh->g != NULL) return; DH_free(dh); dh = NULL;}PSSLDiffieHellman::PSSLDiffieHellman(const PSSLDiffieHellman & diffie){ dh = diffie.dh;}PSSLDiffieHellman & PSSLDiffieHellman::operator=(const PSSLDiffieHellman & diffie){ if (dh != NULL) DH_free(dh); dh = diffie.dh; return *this;}PSSLDiffieHellman::~PSSLDiffieHellman(){ if (dh != NULL) DH_free(dh);}#ifdef __BEOS__// 2/21/04 Yuri Kiryanov - fix for compiler choke on BeOS for usage of// SSL function d2i_DHparams_bio below in PSSLDiffieHellman::Load#undef d2i_DHparams_bio#define d2i_DHparams_bio(bp,x) \ (DH *)ASN1_d2i_bio( \ (char *(*)(...))(void *)DH_new, \ (char *(*)(...))(void *)d2i_DHparams, \ (bp), \ (unsigned char **)(x) \)#endifBOOL PSSLDiffieHellman::Load(const PFilePath & dhFile, PSSLFileTypes fileType){ if (dh != NULL) { DH_free(dh); dh = NULL; } PSSL_BIO in; if (!in.OpenRead(dhFile)) { SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_SYS_LIB); return FALSE; } if (fileType == PSSLFileTypeDEFAULT) fileType = dhFile.GetType() == ".pem" ? PSSLFileTypePEM : PSSLFileTypeASN1; switch (fileType) { case PSSLFileTypeASN1 : dh = d2i_DHparams_bio(in, NULL); if (dh != NULL) return TRUE; SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_ASN1_LIB); break; case PSSLFileTypePEM : dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); if (dh != NULL) return TRUE; SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB); break; default : SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); } return FALSE;}///////////////////////////////////////////////////////////////////////////////static void LockingCallback(int mode, int n, const char * /*file*/, int /*line*/){ static PSSLMutexArray mutexes; if ((mode & CRYPTO_LOCK) != 0) mutexes[n].Wait(); else mutexes[n].Signal();}static int VerifyCallBack(int ok, X509_STORE_CTX * ctx){ X509 * err_cert = X509_STORE_CTX_get_current_cert(ctx); //int err = X509_STORE_CTX_get_error(ctx); // get the subject name, just for verification char buf[256]; X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); PTRACE(1, "SSL\tVerify callback depth " << X509_STORE_CTX_get_error_depth(ctx) << " : cert name = " << buf); return ok;}static void PSSLAssert(const char * msg){ char buf[256]; strcpy(buf, msg); ERR_error_string(ERR_peek_error(), &buf[strlen(msg)]); PTRACE(1, "SSL\t" << buf); PAssertAlways(buf);}PSSLContext::PSSLContext(const void * sessionId, PINDEX idSize){ static PMutex InitialisationMutex; InitialisationMutex.Wait(); static BOOL needInitialisation = TRUE; if (needInitialisation) { SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); // Seed the random number generator BYTE seed[128]; for (size_t i = 0; i < sizeof(seed); i++) seed[i] = (BYTE)rand(); RAND_seed(seed, sizeof(seed)); // set up multithread stuff CRYPTO_set_locking_callback(LockingCallback); needInitialisation = FALSE; } InitialisationMutex.Signal(); // create the new SSL context SSL_METHOD * meth = SSLv23_method(); context = SSL_CTX_new(meth); if (context == NULL) PSSLAssert("Error creating context: "); // Shutdown SSL_CTX_set_quiet_shutdown(context, 1); // Set default locations if (!SSL_CTX_load_verify_locations(context, NULL, ".") || !SSL_CTX_set_default_verify_paths(context)) PSSLAssert("Cannot set CAfile and path: "); if (sessionId != NULL) { if (idSize == 0) idSize = ::strlen((const char *)sessionId)+1; SSL_CTX_set_session_id_context(context, (const BYTE *)sessionId, idSize); SSL_CTX_sess_set_cache_size(context, 128); } // set default verify mode SSL_CTX_set_verify(context, SSL_VERIFY_NONE, VerifyCallBack);}PSSLContext::~PSSLContext(){ SSL_CTX_free(context);}BOOL PSSLContext::SetCAPath(const PDirectory & caPath){ PString path = caPath.Left(caPath.GetLength()-1); if (!SSL_CTX_load_verify_locations(context, NULL, path)) return FALSE; return SSL_CTX_set_default_verify_paths(context);}BOOL PSSLContext::SetCAFile(const PFilePath & caFile){ if (!SSL_CTX_load_verify_locations(context, caFile, NULL)) return FALSE; return SSL_CTX_set_default_verify_paths(context);}BOOL PSSLContext::UseCertificate(const PSSLCertificate & certificate){ 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -