1、SSL初始化:
bool init(string certFile, string privFile) {
SSL_load_error_strings ();
int r = SSL_library_init ();
if (r == 0) {
return false;
}
ssl_ctx = SSL_CTX_new (SSLv23_method ());
if (ssl_ctx == NULL) {
printf("SSL_library_init failed \n");
return false;
}
err_bio = BIO_new_fd(2, BIO_NOCLOSE);
r = SSL_CTX_use_certificate_file(ssl_ctx, certFile.c_str(), SSL_FILETYPE_PEM);
if (r <= 0) {
printf("SSL_CTX_use_certificate_file %s failed \n", certFile.c_str());
return false;
}
r = SSL_CTX_use_PrivateKey_file(ssl_ctx, privFile.c_str(), SSL_FILETYPE_PEM);
if (r <= 0) {
printf("SSL_CTX_use_PrivateKey_file %s failed \n", privFile.c_str());
return false;
}
r = SSL_CTX_check_private_key(ssl_ctx);
if (r == 0) {
printf("SSL_CTX_check_private_key failed \n");
return false;
}
printf("SSL inited success\n");
return true;
}
2、握手协商:
int SSLHandshake()
{
// 在未建立ssl连接之前,应将读写事件添加至epoll中
if (!tcp_connected) {
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLOUT | POLLERR;
int r = poll(&pfd, 1, 0);
if (r == 1 && pfd.revents == POLLOUT) {
printf("tcp connected fd:%d\n", fd);
tcp_connected = true;
//注册读写事件
SetEvent(FD_SEND|FD_RECV|FD_CLOSE|FD_ERROR);
} else {
printf("poll fd:%d return %d revents %d\n", fd, r, pfd.revents);
return -1;
}
}
//如果ssl为null,使用已建立连接的socket初始化ssl
if (ssl == NULL) {
ssl = SSL_new(ssl_ctx);
if (ssl == NULL) {
printf("SSL_new failed, fd:%d \n", fd);
return -1;
}
int r = SSL_set_fd(ssl, fd);
if (r == 0) {
printf("SSL_set_fd failed fd:%d \n", fd);
}
printf("SSL_set_accept_state for fd:%d \n", fd);
SSL_set_accept_state(ssl);
}
int r = SSL_do_handshake(ssl);
//若返回值为1,则SSL握手已完成
if (r == 1) {
ssl_connected = true;
printf("SSL_do_handshake connected success fd:%d\n", fd);
return 0;
}
//处理握手完成后,应该将相应事件移除
int err = SSL_get_error(ssl, r);
if (err == SSL_ERROR_WANT_WRITE) {
//移除读事件
SetEvent(FD_SEND|FD_CLOSE|FD_ERROR);
printf("SSL_get_error return want write set events, fd:%d \n", fd);
return -2;
} else if (err == SSL_ERROR_WANT_READ) {
//移除写事件
SetEvent(FD_RECV|FD_CLOSE|FD_ERROR);
printf("SSL_get_error return want read set events, fd:%d \n", fd);
return -2;
} else {
printf("SSL_get_error return %d error %d errno %d msg %s fd:%d \n"
, r, err, errno, strerror(errno), fd);
return -1;
}
}
知识兔