rocksock_ssl: respect timeouts
[rofl0r-rocksock.git] / rocksock_ssl.c
blobce8f8ab816da526719d19e29ec037ce3f33b5c6c
1 /*
2 * author: rofl0r (C) 2011 - 2013
3 * License: LGPL 2.1+ with static linking exception
4 */
6 #include "rocksock_ssl_internal.h"
7 #include "rocksock_internal.h"
9 #include <openssl/crypto.h>
10 #include <openssl/x509.h>
11 #include <openssl/pem.h>
12 #include <openssl/ssl.h>
13 #include <openssl/err.h>
16 #ifndef ROCKSOCK_FILENAME
17 #define ROCKSOCK_FILENAME __FILE__
18 #endif
20 //RcB: LINK "-lssl -lcrypto -lz"
22 void rocksock_init_ssl(void) {
23 SSL_library_init();
24 SSL_load_error_strings();
25 SSLeay_add_ssl_algorithms();
28 void rocksock_free_ssl(void) {
29 // TODO: there are still 3 memblocks allocated from SSL_library_init (88 bytes)
30 ERR_remove_state(0);
31 ERR_free_strings();
32 EVP_cleanup();
33 CRYPTO_cleanup_all_ex_data();
36 const char* rocksock_ssl_strerror(rocksock *sock, int error) {
37 return ERR_reason_error_string(SSL_get_error(sock->ssl, error));
40 #include <errno.h>
41 int rocksock_ssl_send(rocksock* sock, char* buf, size_t sz) {
42 int ret = SSL_write(sock->ssl, buf, sz);
43 if (ret < 0 && SSL_get_error(sock->ssl, ret) == SSL_ERROR_WANT_WRITE) errno = EWOULDBLOCK;
44 return ret;
47 int rocksock_ssl_recv(rocksock* sock, char* buf, size_t sz) {
48 int ret = SSL_read(sock->ssl, buf, sz);
49 if (ret < 0 && SSL_get_error(sock->ssl, ret) == SSL_ERROR_WANT_READ) errno = EWOULDBLOCK;
50 return ret;
53 int rocksock_ssl_connect_fd(rocksock* sock) {
54 sock->sslctx = SSL_CTX_new(SSLv23_client_method());
55 if (!sock->sslctx) {
56 ERR_print_errors_fp(stderr);
57 return rocksock_seterror(sock, RS_ET_OWN, RS_E_SSL_GENERIC, ROCKSOCK_FILENAME, __LINE__);
59 sock->ssl = SSL_new(sock->sslctx);
60 if (!sock->ssl) {
61 ERR_print_errors_fp(stderr);
62 return rocksock_seterror(sock, RS_ET_OWN, RS_E_SSL_GENERIC, ROCKSOCK_FILENAME, __LINE__);
64 SSL_set_fd(sock->ssl, sock->socket);
65 int ret = SSL_connect(sock->ssl);
66 if(ret != 1) {
67 if((ret = SSL_get_error(sock->ssl, ret)) == SSL_ERROR_WANT_READ)
68 return rocksock_seterror(sock, RS_ET_OWN, RS_E_HIT_CONNECTTIMEOUT, ROCKSOCK_FILENAME, __LINE__);
69 //ERR_print_errors_fp(stderr);
70 //printf("%dxxx\n", SSL_get_error(sock->ssl, ret));
71 return rocksock_seterror(sock, RS_ET_SSL, ret, ROCKSOCK_FILENAME, __LINE__);
73 return 0;
76 void rocksock_ssl_free_context(rocksock *sock) {
77 if(sock->ssl) {
78 SSL_shutdown(sock->ssl);
79 SSL_free(sock->ssl);
80 SSL_CTX_free(sock->sslctx);
81 sock->ssl = 0;
85 int rocksock_ssl_pending(rocksock *sock) {
86 return SSL_pending(sock->ssl);
89 int rocksock_ssl_peek(rocksock* sock, int *result) {
90 char buf[4];
91 int ret;
92 again:
93 ret = SSL_peek(sock->ssl, buf, 1);
94 if(ret >= 0) *result = 1;
95 else {
96 ret = SSL_get_error(sock->ssl, ret);
97 if(ret == SSL_ERROR_WANT_READ)
98 return rocksock_seterror(sock, RS_ET_OWN, RS_E_HIT_READTIMEOUT, ROCKSOCK_FILENAME, __LINE__); //goto again;
99 return rocksock_seterror(sock, RS_ET_SSL, ret, ROCKSOCK_FILENAME, __LINE__);
101 return rocksock_seterror(sock, RS_ET_NO_ERROR, 0, NULL, 0);