add LGPL 2.1 license
[rofl0r-rocksock.git] / rocksock_openssl.c
blob2f54504bdcc2ca5fc2b86fbbfd0467a1c6187e5b
1 /*
2 * author: rofl0r (C) 2011 - 2013
3 * License: LGPL 2.1+ with static linking exception
4 */
6 #ifdef USE_OPENSSL
8 #include "rocksock_ssl_internal.h"
9 #include "rocksock_internal.h"
11 #include <openssl/crypto.h>
12 #include <openssl/x509.h>
13 #include <openssl/pem.h>
14 #include <openssl/ssl.h>
15 #include <openssl/err.h>
18 #ifndef ROCKSOCK_FILENAME
19 #define ROCKSOCK_FILENAME __FILE__
20 #endif
22 #pragma RcB2 LINK "-lssl" "-lcrypto" "-lz"
24 void rocksock_init_ssl(void) {
25 SSL_library_init();
26 SSL_load_error_strings();
27 SSLeay_add_ssl_algorithms();
30 void rocksock_free_ssl(void) {
31 // TODO: there are still 3 memblocks allocated from SSL_library_init (88 bytes)
32 ERR_remove_state(0);
33 ERR_free_strings();
34 EVP_cleanup();
35 CRYPTO_cleanup_all_ex_data();
38 const char* rocksock_ssl_strerror(rocksock *sock, int error) {
39 return ERR_reason_error_string(error);
42 #include <errno.h>
43 int rocksock_ssl_send(rocksock* sock, char* buf, size_t sz) {
44 int ret = SSL_write(sock->ssl, buf, sz);
45 if (ret < 0 && SSL_get_error(sock->ssl, ret) == SSL_ERROR_WANT_WRITE) errno = EWOULDBLOCK;
46 return ret;
49 int rocksock_ssl_recv(rocksock* sock, char* buf, size_t sz) {
50 int ret = SSL_read(sock->ssl, buf, sz);
51 if (ret < 0 && SSL_get_error(sock->ssl, ret) == SSL_ERROR_WANT_READ) errno = EWOULDBLOCK;
52 return ret;
55 int rocksock_ssl_connect_fd(rocksock* sock) {
56 sock->sslctx = SSL_CTX_new(SSLv23_client_method());
57 if (!sock->sslctx) {
58 ERR_print_errors_fp(stderr);
59 return rocksock_seterror(sock, RS_ET_OWN, RS_E_SSL_GENERIC, ROCKSOCK_FILENAME, __LINE__);
61 sock->ssl = SSL_new(sock->sslctx);
62 if (!sock->ssl) {
63 ERR_print_errors_fp(stderr);
64 return rocksock_seterror(sock, RS_ET_OWN, RS_E_SSL_GENERIC, ROCKSOCK_FILENAME, __LINE__);
66 SSL_set_fd(sock->ssl, sock->socket);
67 int ret = SSL_connect(sock->ssl);
68 if(ret != 1) {
69 if((ret = SSL_get_error(sock->ssl, ret)) == SSL_ERROR_WANT_READ)
70 return rocksock_seterror(sock, RS_ET_OWN, RS_E_HIT_CONNECTTIMEOUT, ROCKSOCK_FILENAME, __LINE__);
71 //ERR_print_errors_fp(stderr);
72 //printf("%dxxx\n", SSL_get_error(sock->ssl, ret));
73 return rocksock_seterror(sock, RS_ET_SSL, ret, ROCKSOCK_FILENAME, __LINE__);
75 return 0;
78 void rocksock_ssl_free_context(rocksock *sock) {
79 if(sock->ssl) {
80 SSL_shutdown(sock->ssl);
81 SSL_free(sock->ssl);
82 SSL_CTX_free(sock->sslctx);
83 sock->ssl = 0;
87 int rocksock_ssl_pending(rocksock *sock) {
88 return SSL_pending(sock->ssl);
91 int rocksock_ssl_peek(rocksock* sock, int *result) {
92 char buf[4];
93 int ret;
94 ret = SSL_peek(sock->ssl, buf, 1);
95 if(ret >= 0) *result = 1;
96 else {
97 ret = SSL_get_error(sock->ssl, ret);
98 if(ret == SSL_ERROR_WANT_READ)
99 return rocksock_seterror(sock, RS_ET_OWN, RS_E_HIT_READTIMEOUT, ROCKSOCK_FILENAME, __LINE__);
100 return rocksock_seterror(sock, RS_ET_SSL, ret, ROCKSOCK_FILENAME, __LINE__);
102 return rocksock_seterror(sock, RS_ET_OWN, 0, NULL, 0);
105 #endif