|
|
|
@ -6,10 +6,12 @@
|
|
|
|
|
#include <unistd.h> /* close() */
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h> /* memset() */
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <openssl/ssl.h>
|
|
|
|
|
#include <openssl/err.h>
|
|
|
|
|
|
|
|
|
@ -22,6 +24,8 @@ SSLSocket::SSLSocket() {
|
|
|
|
|
writecnt = 0;
|
|
|
|
|
certfile = "";
|
|
|
|
|
keyfile = "";
|
|
|
|
|
sslerror = SSL_ERROR_NONE;
|
|
|
|
|
timeout = 0;
|
|
|
|
|
ctx = NULL;
|
|
|
|
|
ssl = NULL;
|
|
|
|
|
if (ssl_init == 0) {
|
|
|
|
@ -95,33 +99,54 @@ int SSLSocket::SetCertificat(string certf, string keyf) {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int SSLSocket::Connect (int sockfd) {
|
|
|
|
|
int SSLSocket::Connect (int sockfd, int block_timeout) {
|
|
|
|
|
int flags, res;
|
|
|
|
|
|
|
|
|
|
TimeoutReset();
|
|
|
|
|
sslerror = SSL_ERROR_NONE;
|
|
|
|
|
NewClientCTX();
|
|
|
|
|
timeout = block_timeout;
|
|
|
|
|
|
|
|
|
|
if (sockfd > 0 && block_timeout > 0) {
|
|
|
|
|
flags = fcntl(sockfd, F_GETFL, 0);
|
|
|
|
|
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssl = SSL_new(ctx);
|
|
|
|
|
SSL_set_fd (ssl, sockfd);
|
|
|
|
|
if (SSL_connect(ssl) == -1 ) {
|
|
|
|
|
printf ("ssl connect: error\n");
|
|
|
|
|
ERR_print_errors_fp(stderr);
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
res = SSL_connect(ssl);
|
|
|
|
|
if (res == -1) sslerror = SSL_get_error(ssl, -1);
|
|
|
|
|
} while (res == -1 && TimeoutTime() < timeout &&
|
|
|
|
|
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
|
|
|
|
|
|
|
|
|
|
if (res == -1) return 0;
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int SSLSocket::Accept (int sockfd) {
|
|
|
|
|
int err;
|
|
|
|
|
int SSLSocket::Accept (int sockfd, int block_timeout) {
|
|
|
|
|
int flags, res;
|
|
|
|
|
|
|
|
|
|
TimeoutReset();
|
|
|
|
|
sslerror = SSL_ERROR_NONE;
|
|
|
|
|
timeout = block_timeout;
|
|
|
|
|
NewServerCTX();
|
|
|
|
|
|
|
|
|
|
if (sockfd > 0 && block_timeout > 0) {
|
|
|
|
|
flags = fcntl(sockfd, F_GETFL, 0);
|
|
|
|
|
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssl = SSL_new(ctx);
|
|
|
|
|
SSL_set_fd (ssl, sockfd);
|
|
|
|
|
if (SSL_accept(ssl) == -1 ) {
|
|
|
|
|
err = SSL_get_error(ssl, -1);
|
|
|
|
|
printf ("%s %s:%d error: %s\n", __FUNCTION__, __FILE__, __LINE__, GetSSLErrorText(err).c_str());
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
do {
|
|
|
|
|
res = SSL_accept(ssl);
|
|
|
|
|
if (res == -1) sslerror = SSL_get_error(ssl, -1);
|
|
|
|
|
} while (res == -1 && TimeoutTime() < timeout &&
|
|
|
|
|
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
@ -175,6 +200,7 @@ const string SSLSocket::GetSSLErrorText(int err) {
|
|
|
|
|
// close ssl and return socket.
|
|
|
|
|
int SSLSocket::Close () {
|
|
|
|
|
int sock = 0;
|
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
|
|
if (ssl) {
|
|
|
|
|
sock = SSL_get_fd(ssl);
|
|
|
|
@ -187,37 +213,74 @@ int SSLSocket::Close () {
|
|
|
|
|
ctx = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sock > 0 && timeout > 0) {
|
|
|
|
|
flags = fcntl(sock, F_GETFL, 0);
|
|
|
|
|
fcntl(sock, F_SETFL, flags & ~(O_NONBLOCK));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sock;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// need to add timeout currently data is blocking
|
|
|
|
|
//
|
|
|
|
|
long int SSLSocket::Read (char *buffer, long int len) {
|
|
|
|
|
int ret;
|
|
|
|
|
sslerror = SSL_ERROR_NONE;
|
|
|
|
|
|
|
|
|
|
TimeoutReset();
|
|
|
|
|
|
|
|
|
|
if (!ssl) {
|
|
|
|
|
errno = EPROTO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = SSL_read(ssl, buffer, len);
|
|
|
|
|
do {
|
|
|
|
|
ret = SSL_read(ssl, buffer, len);
|
|
|
|
|
if (ret == -1) sslerror = SSL_get_error(ssl, -1);
|
|
|
|
|
} while (ret == -1 && TimeoutTime() < timeout &&
|
|
|
|
|
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// need to add timeout currently data is blocking
|
|
|
|
|
//
|
|
|
|
|
long int SSLSocket::Write (char *buffer, long int len) {
|
|
|
|
|
int ret;
|
|
|
|
|
sslerror = SSL_ERROR_NONE;
|
|
|
|
|
TimeoutReset();
|
|
|
|
|
|
|
|
|
|
if (!ssl) {
|
|
|
|
|
errno = EPROTO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = SSL_write(ssl, buffer, len);
|
|
|
|
|
do {
|
|
|
|
|
ret = SSL_write(ssl, buffer, len);
|
|
|
|
|
if (ret == -1) sslerror = SSL_get_error(ssl, -1);
|
|
|
|
|
} while (ret == -1 && TimeoutTime() < timeout &&
|
|
|
|
|
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reset Timeout Timer
|
|
|
|
|
void SSLSocket::TimeoutReset() {
|
|
|
|
|
gettimeofday (&timeout_start, NULL);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Return time which has past since reset in ms.
|
|
|
|
|
int SSLSocket::TimeoutTime() {
|
|
|
|
|
struct timeval tv;
|
|
|
|
|
gettimeofday (&tv, NULL);
|
|
|
|
|
|
|
|
|
|
return ((tv.tv_sec-timeout_start.tv_sec) * 1000) +
|
|
|
|
|
((tv.tv_usec-timeout_start.tv_usec) / 1000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|