📄 ssl.cpp
字号:
/* Copyright (C) 2000-2007 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.*//* SSL source implements all openssl compatibility API functions * * TODO: notes are mostly api additions to allow compilation with mysql * they don't affect normal modes but should be provided for completeness * stunnel functions at end of file *//* see man pages for function descriptions */#include "runtime.hpp"#include "openssl/ssl.h"#include "handshake.hpp"#include "yassl_int.hpp"#include "md5.hpp" // for TaoCrypt MD5 size assert#include "md4.hpp" // for TaoCrypt MD4 size assert#include "file.hpp" // for TaoCrypt Source#include "coding.hpp" // HexDecoder#include "helpers.hpp" // for placement new hack#include <stdio.h>#ifdef _WIN32 #include <windows.h> // FindFirstFile etc..#else #include <sys/types.h> // file helper #include <sys/stat.h> // stat #include <dirent.h> // opendir#endifnamespace yaSSL {int read_file(SSL_CTX* ctx, const char* file, int format, CertType type){ if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) return SSL_BAD_FILETYPE; if (file == NULL || !file[0]) return SSL_BAD_FILE; FILE* input = fopen(file, "rb"); if (!input) return SSL_BAD_FILE; if (type == CA) { // may have a bunch of CAs x509* ptr; while ( (ptr = PemToDer(input, Cert)) ) ctx->AddCA(ptr); if (!feof(input)) { fclose(input); return SSL_BAD_FILE; } } else { x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_; if (format == SSL_FILETYPE_ASN1) { fseek(input, 0, SEEK_END); long sz = ftell(input); rewind(input); x = NEW_YS x509(sz); // takes ownership size_t bytes = fread(x->use_buffer(), sz, 1, input); if (bytes != 1) { fclose(input); return SSL_BAD_FILE; } } else { EncryptedInfo info; x = PemToDer(input, type, &info); if (!x) { fclose(input); return SSL_BAD_FILE; } if (info.set) { // decrypt char password[80]; pem_password_cb cb = ctx->GetPasswordCb(); if (!cb) { fclose(input); return SSL_BAD_FILE; } int passwordSz = cb(password, sizeof(password), 0, ctx->GetUserData()); byte key[AES_256_KEY_SZ]; // max sizes byte iv[AES_IV_SZ]; // use file's salt for key derivation, but not real iv TaoCrypt::Source source(info.iv, info.ivSz); TaoCrypt::HexDecoder dec(source); memcpy(info.iv, source.get_buffer(), min((uint)sizeof(info.iv), source.size())); EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password, passwordSz, 1, key, iv); mySTL::auto_ptr<BulkCipher> cipher; if (strncmp(info.name, "DES-CBC", 7) == 0) cipher.reset(NEW_YS DES); else if (strncmp(info.name, "DES-EDE3-CBC", 13) == 0) cipher.reset(NEW_YS DES_EDE); else if (strncmp(info.name, "AES-128-CBC", 13) == 0) cipher.reset(NEW_YS AES(AES_128_KEY_SZ)); else if (strncmp(info.name, "AES-192-CBC", 13) == 0) cipher.reset(NEW_YS AES(AES_192_KEY_SZ)); else if (strncmp(info.name, "AES-256-CBC", 13) == 0) cipher.reset(NEW_YS AES(AES_256_KEY_SZ)); else { fclose(input); return SSL_BAD_FILE; } cipher->set_decryptKey(key, info.iv); mySTL::auto_ptr<x509> newx(NEW_YS x509(x->get_length())); cipher->decrypt(newx->use_buffer(), x->get_buffer(), x->get_length()); ysDelete(x); x = newx.release(); } } } fclose(input); return SSL_SUCCESS;}extern "C" {SSL_METHOD* SSLv3_method(){ return SSLv3_client_method();}SSL_METHOD* SSLv3_server_method(){ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,0));}SSL_METHOD* SSLv3_client_method(){ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,0));}SSL_METHOD* TLSv1_server_method(){ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1));}SSL_METHOD* TLSv1_client_method(){ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1));}SSL_METHOD* TLSv1_1_server_method(){ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2));}SSL_METHOD* TLSv1_1_client_method(){ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2));}SSL_METHOD* SSLv23_server_method(){ // compatibility only, no version 2 support, but does SSL 3 and TLS 1 return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2), true);}SSL_METHOD* SSLv23_client_method(){ // compatibility only, no version 2 support, but does SSL 3 and TLS 1 // though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline // TODO: maybe add support to send SSLv2 hello ??? return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2), true);}SSL_CTX* SSL_CTX_new(SSL_METHOD* method){ return NEW_YS SSL_CTX(method);}void SSL_CTX_free(SSL_CTX* ctx){ ysDelete(ctx);}SSL* SSL_new(SSL_CTX* ctx){ return NEW_YS SSL(ctx);}void SSL_free(SSL* ssl){ ysDelete(ssl);}int SSL_set_fd(SSL* ssl, YASSL_SOCKET_T fd){ ssl->useSocket().set_fd(fd); return SSL_SUCCESS;}YASSL_SOCKET_T SSL_get_fd(const SSL* ssl){ return ssl->getSocket().get_fd();}int SSL_connect(SSL* ssl){ if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl->SetError(no_error); ClientState neededState; switch (ssl->getStates().GetConnect()) { case CONNECT_BEGIN : sendClientHello(*ssl); if (!ssl->GetError()) ssl->useStates().UseConnect() = CLIENT_HELLO_SENT; case CLIENT_HELLO_SENT : neededState = ssl->getSecurity().get_resuming() ? serverFinishedComplete : serverHelloDoneComplete; while (ssl->getStates().getClient() < neededState) { if (ssl->GetError()) break; processReply(*ssl); } if (!ssl->GetError()) ssl->useStates().UseConnect() = FIRST_REPLY_DONE; case FIRST_REPLY_DONE : if(ssl->getCrypto().get_certManager().sendVerify()) sendCertificate(*ssl); if (!ssl->getSecurity().get_resuming()) sendClientKeyExchange(*ssl); if(ssl->getCrypto().get_certManager().sendVerify()) sendCertificateVerify(*ssl); sendChangeCipher(*ssl); sendFinished(*ssl, client_end); ssl->flushBuffer(); if (!ssl->GetError()) ssl->useStates().UseConnect() = FINISHED_DONE; case FINISHED_DONE : if (!ssl->getSecurity().get_resuming()) while (ssl->getStates().getClient() < serverFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } if (!ssl->GetError()) ssl->useStates().UseConnect() = SECOND_REPLY_DONE; case SECOND_REPLY_DONE : ssl->verifyState(serverFinishedComplete); ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); if (ssl->GetError()) { GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; } return SSL_SUCCESS; default : return SSL_FATAL_ERROR; // unkown state }}int SSL_write(SSL* ssl, const void* buffer, int sz){ return sendData(*ssl, buffer, sz);}int SSL_read(SSL* ssl, void* buffer, int sz){ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer)); return receiveData(*ssl, data);}int SSL_accept(SSL* ssl){ if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl->SetError(no_error); switch (ssl->getStates().GetAccept()) { case ACCEPT_BEGIN : processReply(*ssl); if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE; case ACCEPT_FIRST_REPLY_DONE : sendServerHello(*ssl); if (!ssl->getSecurity().get_resuming()) { sendCertificate(*ssl); if (ssl->getSecurity().get_connection().send_server_key_) sendServerKeyExchange(*ssl); if(ssl->getCrypto().get_certManager().verifyPeer()) sendCertificateRequest(*ssl); sendServerHelloDone(*ssl); ssl->flushBuffer(); } if (!ssl->GetError()) ssl->useStates().UseAccept() = SERVER_HELLO_DONE; case SERVER_HELLO_DONE : if (!ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE; case ACCEPT_SECOND_REPLY_DONE : sendChangeCipher(*ssl); sendFinished(*ssl, server_end); ssl->flushBuffer(); if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE; case ACCEPT_FINISHED_DONE : if (ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE; case ACCEPT_THIRD_REPLY_DONE : ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); if (ssl->GetError()) { GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; } return SSL_SUCCESS; default: return SSL_FATAL_ERROR; // unknown state }}int SSL_do_handshake(SSL* ssl){ if (ssl->getSecurity().get_parms().entity_ == client_end) return SSL_connect(ssl); else return SSL_accept(ssl);}int SSL_clear(SSL* ssl){ GetErrors().Remove(); return SSL_SUCCESS;}int SSL_shutdown(SSL* ssl){ if (!ssl->GetQuietShutdown()) { Alert alert(warning, close_notify); sendAlert(*ssl, alert); } ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true); GetErrors().Remove(); return SSL_SUCCESS;}void SSL_set_quiet_shutdown(SSL *ssl,int mode){ ssl->SetQuietShutdown(mode != 0);}int SSL_get_quiet_shutdown(SSL *ssl){ return ssl->GetQuietShutdown();}/* on by default but allow user to turn off */long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode){ if (mode == SSL_SESS_CACHE_OFF) ctx->SetSessionCacheOff(); return SSL_SUCCESS;}SSL_SESSION* SSL_get_session(SSL* ssl){ if (ssl->getSecurity().GetContext()->GetSessionCacheOff()) return 0; return GetSessions().lookup( ssl->getSecurity().get_connection().sessionID_);}int SSL_set_session(SSL* ssl, SSL_SESSION* session){ if (ssl->getSecurity().GetContext()->GetSessionCacheOff()) return SSL_FAILURE; ssl->set_session(session); return SSL_SUCCESS;}int SSL_session_reused(SSL* ssl){ return ssl->getSecurity().get_resuming();}long SSL_SESSION_set_timeout(SSL_SESSION* sess, long t){ if (!sess) return SSL_ERROR_NONE; sess->SetTimeOut(t); return SSL_SUCCESS;}long SSL_get_default_timeout(SSL* /*ssl*/){ return DEFAULT_TIMEOUT;}const char* SSL_get_cipher_name(SSL* ssl){ return SSL_get_cipher(ssl); }const char* SSL_get_cipher(SSL* ssl){ return ssl->getSecurity().get_parms().cipher_name_;}// SSLv2 only, not implementedchar* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len){ return strncpy(buf, "Not Implemented, SSLv2 only", len);}const char* SSL_get_cipher_list(SSL* ssl, int priority){ if (priority < 0 || priority >= MAX_CIPHERS) return 0; if (ssl->getSecurity().get_parms().cipher_list_[priority][0]) return ssl->getSecurity().get_parms().cipher_list_[priority]; return 0;}int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list){ if (ctx->SetCipherList(list)) return SSL_SUCCESS; else return SSL_FAILURE;}const char* SSL_get_version(SSL* ssl){ static const char* version3 = "SSLv3"; static const char* version31 = "TLSv1"; return ssl->isTLS() ? version31 : version3;}const char* SSLeay_version(int){ static const char* version = "SSLeay yaSSL compatibility"; return version;}int SSL_get_error(SSL* ssl, int /*previous*/){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -