LINK=libtool --mode=link ${CC} ${LDFLAGS}
INSTALL=libtool --mode=install install
-CFLAGS_LIB=-Wall -fPIC -c -g -I${top_srcdir}/src ${LIBCARES_CFLAGS} ${LIBSSL_CFLAGS}
+CFLAGS_LIB=-Wall -pedantic -fPIC -c -g -I${top_srcdir}/src ${LIBCARES_CFLAGS} ${LIBSSL_CFLAGS}
LFLAGS_LIB=-shared ${LIBCARES_LIBS} ${LIBSSL_LIBS}
CFLAGS_CLI=-Wall -g -I${top_srcdir}/src
#define BACKLOG 10 //TODO just for testing - max incoming connections
-static int io_clear(glb_ctx *cc, io_handler *io);
+static void io_destroy(glb_ctx *cc, io_handler *io);
static int init_io_content(glb_ctx *cc, io_handler *io);
canl_ctx canl_create_ctx()
{
int sock;
struct sockaddr_in *sa_in = NULL;
int i = 0;
- int err_clear = 0;
/*check cc and io*/
if (!glb_cc) {
end:
if (err) {
update_error(cc, "failed to connect (canl_io_connect)");
- if ((err_clear = io_clear(glb_cc, io_cc)))
- update_error(cc, "failed to clean io_handler"
- " (canl_io_connect)");
}
return err;
}
}
if (!io) {
- //set_error(ctx->err_msg);
err = EINVAL;
- goto end;
+ set_error(glb_cc, err, posix_error, "invalid io handler"
+ " canl_io_close)");
+ return err;
}
+ return err;
+
/*ssl close*/
/*set cc and io accordingly*/
-
-end:
- if (err)
- update_error(glb_cc, "cannot close connection (canl_io_close)");
- return err;
}
-static int io_clear(glb_ctx *cc, io_handler *io)
+static void io_destroy(glb_ctx *cc, io_handler *io)
{
io_handler *io_cc = (io_handler*) io;
glb_ctx *glb_cc = (glb_ctx*) cc;
int err = 0;
- /*check cc and io*/
- if (!cc) {
- return EINVAL;
- }
-
- if (!io) {
- err = EINVAL;
- goto end;
- }
+ unsigned long ssl_err;
+ CANL_ERROR_ORIGIN e_orig = unknown_error;
// delete io_handler content
if (io_cc->ar) {
free (io_cc->s_addr);
io_cc->s_addr = NULL;
}
-
-end:
- if (err)
- update_error(glb_cc, "cannot clear io_handle (io_clear)");
- return err;
-
+ if (io_cc->s_ctx) {
+ /*TODO maybe new function because of BIO_free and SSL_free*/
+ if (io_cc->s_ctx->ssl_io) {
+ SSL_free(io_cc->s_ctx->ssl_io);
+ io_cc->s_ctx->ssl_io = NULL;
+ }
+ if (io_cc->s_ctx->bio_conn) {
+ err = BIO_free(io_cc->s_ctx->bio_conn);
+ /* TODO check it?
+ if (!err) {
+ ssl_err = ERR_peek_error();
+ set_error(io_cc, err, ssl_error, "cannot free BIO"
+ " (io_destroy)");
+ err = 1;
+ } */
+ io_cc->s_ctx->bio_conn = NULL;
+ }
+ }
+ free (io_cc->s_ctx);
+ io_cc->s_ctx = NULL;
}
int canl_io_destroy(canl_ctx cc, canl_io_handler io)
glb_ctx *glb_cc = (glb_ctx*) cc;
io_handler *io_cc = (io_handler*) io;
/*check cc and io*/
- if (!cc) {
+ if (!glb_cc) {
return EINVAL;
}
- if (!io) {
- //set_error(ctx->err_msg);
+ if (!io_cc) {
err = EINVAL;
- goto end;
+ set_error(glb_cc, err, posix_error, "invalid io handler"
+ " canl_io_destroy)");
+ return err;
}
- err = io_clear(glb_cc, io_cc);
- if (err)
- goto end;
+ err = ssl_close(glb_cc, io_cc);
+ if (err <= 0)
+ return err;
+
+ io_destroy(glb_cc, io_cc);
// delete io itself
if (io_cc) {
free (io_cc);
- io = NULL;
+ io_cc = NULL;
}
-end:
- if (err)
- update_error(glb_cc, "can't destroy io_handle (canl_io_destroy)");
+
return err;
}
#ifndef _CANL_H
#define _CANL_H
#include <sys/time.h>
-#include "canl_err.h"
typedef void *canl_io_handler;
typedef void *canl_ctx;
/*TODO NULL NULL, callback and user data*/
cc->cert_key->key = PEM_read_PrivateKey(key_file, NULL, NULL, NULL);
if (!cc->cert_key->key) {
- ssl_err = ERR_get_error();
+ ssl_err = ERR_peek_error();
set_error(cc, ssl_err, ssl_error, "error while writing key to context"
" (set_key_file)");
goto end;
int separ_len = 0;
const char *msg_pref = "[CANL:MSG] ";
int msg_pref_len = 0;
+ glb_ctx *ctx = (glb_ctx*) cc;
code_str[0] = '\0';
- glb_ctx *ctx = (glb_ctx*) cc;
-
/*check cc*/
if (!ctx) {
return EINVAL;
#include <openssl/safestack.h>
#include <unistd.h>
#include <fcntl.h>
+#include "canl_err.h"
#include "canl.h"
typedef struct _cert_key_store {
struct timeval *tout);
int ssl_write(glb_ctx *cc, io_handler *io, void *buffer, size_t size,
struct timeval *tout);
+int ssl_close(glb_ctx *cc, io_handler *io);
int do_set_ctx_own_cert(glb_ctx *cc, canl_x509 cert, canl_stack_of_x509 chain,
canl_pkey key);
#include "canl_locl.h"
-#define SSL_SERVER_METH SSLv3_server_method()
+#define SSL_SERVER_METH SSLv23_server_method()
#define SSL_CLIENT_METH SSLv3_client_method()
+#define DESTROY_TIMEOUT 10
static int do_ssl_connect( glb_ctx *cc, io_handler *io, struct timeval *timeout);
static int do_ssl_accept( glb_ctx *cc, io_handler *io, struct timeval *timeout);
goto end;
}
- SSL_load_error_strings();
SSL_library_init();
+ SSL_load_error_strings();
//OpenSSL_add_all_algorithms();
//OpenSSL_add_all_ciphers();
ERR_clear_error();
*/
int do_select(int fd, time_t starttime, int timeout, int wanted)
{
+ int ret = 0;
fd_set rset;
fd_set wset;
if (wanted == 0 || wanted == SSL_ERROR_WANT_WRITE)
FD_SET(fd, &wset);
- int ret = 0;
-
if (timeout != -1) {
struct timeval endtime;
return err;
}
+/* ret > 1 if connection does not exist or has been closed before
+ * ret = 0 connection closed successfully (one direction)
+ * ret = 1 connection closed successfully (both directions)
+ * ret < 0 error occured (e.g. timeout reached) */
+int ssl_close(glb_ctx *cc, io_handler *io)
+{
+ int timeout = DESTROY_TIMEOUT;
+ time_t starttime, curtime;
+ int expected = 0, error = 0, ret = 0, ret2 = 0;
+ int fd;
+ unsigned long ssl_err = 0;
+
+ if (!io->s_ctx->ssl_io) {
+ return 2;
+ }
+
+ fd = BIO_get_fd(SSL_get_rbio(io->s_ctx->ssl_io), NULL);
+ curtime = starttime = time(NULL);
+
+ /* check the shutdown state*/
+ ret = SSL_get_shutdown(io->s_ctx->ssl_io);
+ if (ret & SSL_SENT_SHUTDOWN)
+ if (ret & SSL_RECEIVED_SHUTDOWN)
+ return 1;
+ else
+ return 0;
+ /* TODO check the proper states, maybe also call SSL_shutdown
+ if (ret & SSL_RECEIVED_SHUTDOWN) {
+ return 0;
+ } */
+
+ do {
+ ret = do_select(fd, starttime, timeout, expected);
+ curtime = time(NULL);
+
+ if (ret > 0) {
+ ret2 = SSL_shutdown(io->s_ctx->ssl_io);
+ if (ret2 < 0) {
+ ssl_err = ERR_peek_error();
+ expected = error = SSL_get_error(io->s_ctx->ssl_io, ret2);
+ }
+ }
+ } while (TEST_SELECT(ret, ret2, timeout, curtime, starttime, error));
+
+ if (timeout != -1 && (curtime - starttime >= timeout)){
+ set_error(cc, ETIMEDOUT, posix_error, "Connection stuck"
+ " during ssl shutdown : timeout reached. (ssl_close)");
+ return -1;
+ }
+ /* TODO set_error*/
+ if (ret < 0) {
+ set_error(cc, 0, unknown_error, "Error during SSL"
+ " shutdown: (ssl_close)");
+ return -1;
+ }
+ /* successful shutdown (uni/bi directional)*/
+ if (ret2 == 0 || ret2 == 1)
+ return ret2;
+ else {
+ set_error(cc, ssl_err, ssl_error, "Error during SSL"
+ " shutdown: (ssl_close)");
+ return -1;
+ }
+}
+
static void dbg_print_ssl_error(int errorcode)
{
printf("[DBG CANL] ");