diff --git a/stio/lib/main.c b/stio/lib/main.c index 46f6bd5..3502c31 100644 --- a/stio/lib/main.c +++ b/stio/lib/main.c @@ -425,8 +425,9 @@ int main () memset (&tcp_bind, 0, STIO_SIZEOF(tcp_bind)); stio_sckaddr_initforip4 (&tcp_bind.localaddr, 1235, STIO_NULL); tcp_bind.options = STIO_DEV_SCK_BIND_REUSEADDR | /*STIO_DEV_SCK_BIND_REUSEPORT |*/ STIO_DEV_SCK_BIND_SSL; - tcp_bind.certfile = STIO_MT("localhost.crt"); - tcp_bind.keyfile = STIO_MT("localhost.key"); + tcp_bind.ssl_certfile = STIO_MT("localhost.crt"); + tcp_bind.ssl_keyfile = STIO_MT("localhost.key"); + //stio_inittime (&tcp_bind.ssl_accept_tmout, 0, 1); if (stio_dev_sck_bind (tcp[2],&tcp_bind) <= -1) { diff --git a/stio/lib/stio-sck.c b/stio/lib/stio-sck.c index 1fb9e18..93d76b2 100644 --- a/stio/lib/stio-sck.c +++ b/stio/lib/stio-sck.c @@ -285,6 +285,18 @@ static void tmr_connect_handle (stio_t* stio, const stio_ntime_t* now, stio_tmrj } } +static void ssl_accept_timedout (stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* job) +{ + stio_dev_sck_t* rdev = (stio_dev_sck_t*)job->ctx; + + STIO_ASSERT (IS_STATEFUL(rdev)); + + if (rdev->state & STIO_DEV_SCK_ACCEPTING_SSL) + { + stio_dev_sck_halt(rdev); + } +} + /* ======================================================================== */ static int dev_sck_make (stio_dev_t* dev, void* ctx) @@ -301,7 +313,7 @@ static int dev_sck_make (stio_dev_t* dev, void* ctx) rdev->on_write = arg->on_write; rdev->on_read = arg->on_read; rdev->type = arg->type; - rdev->tmridx_connect = STIO_TMRIDX_INVALID; + rdev->tmrjob_index = STIO_TMRIDX_INVALID; return 0; @@ -324,6 +336,8 @@ static int dev_sck_make_client (stio_dev_t* dev, void* ctx) * after a client socket has been created. */ rdev->sck = *sck; + rdev->tmrjob_index = STIO_TMRIDX_INVALID; + if (stio_makesckasync (rdev->stio, rdev->sck) <= -1) return -1; #if defined(FD_CLOEXEC) { @@ -350,16 +364,16 @@ static int dev_sck_kill (stio_dev_t* dev, int force) if (rdev->on_disconnect) rdev->on_disconnect (rdev); } - if (rdev->tmridx_connect != STIO_TMRIDX_INVALID) + if (rdev->tmrjob_index != STIO_TMRIDX_INVALID) { - stio_deltmrjob (dev->stio, rdev->tmridx_connect); - STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID); + stio_deltmrjob (dev->stio, rdev->tmrjob_index); + STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID); } } else { STIO_ASSERT (rdev->state == 0); - STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID); + STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID); } #if defined(USE_SSL) @@ -369,10 +383,10 @@ static int dev_sck_kill (stio_dev_t* dev, int force) SSL_free ((SSL*)rdev->ssl); rdev->ssl = STIO_NULL; } - if (!(rdev->state & (STIO_DEV_SCK_ACCEPTED | STIO_DEV_SCK_ACCEPTING_SSL)) && rdev->sslctx) + if (!(rdev->state & (STIO_DEV_SCK_ACCEPTED | STIO_DEV_SCK_ACCEPTING_SSL)) && rdev->ssl_ctx) { - SSL_CTX_free ((SSL_CTX*)rdev->sslctx); - rdev->sslctx = STIO_NULL; + SSL_CTX_free ((SSL_CTX*)rdev->ssl_ctx); + rdev->ssl_ctx = STIO_NULL; } #endif @@ -622,7 +636,7 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) if (bnd->options & STIO_DEV_SCK_BIND_SSL) { #if defined(USE_SSL) - if (!bnd->certfile || !bnd->keyfile) + if (!bnd->ssl_certfile || !bnd->ssl_keyfile) { rdev->stio->errnum = STIO_EINVAL; return -1; @@ -635,8 +649,8 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) return -1; } - if (SSL_CTX_use_certificate_file (ssl_ctx, bnd->certfile, SSL_FILETYPE_PEM) == 0 || - SSL_CTX_use_PrivateKey_file (ssl_ctx, bnd->keyfile, SSL_FILETYPE_PEM) == 0 || + if (SSL_CTX_use_certificate_file (ssl_ctx, bnd->ssl_certfile, SSL_FILETYPE_PEM) == 0 || + SSL_CTX_use_PrivateKey_file (ssl_ctx, bnd->ssl_keyfile, SSL_FILETYPE_PEM) == 0 || SSL_CTX_check_private_key (ssl_ctx) == 0 /*|| SSL_CTX_use_certificate_chain_file (ssl_ctx, bnd->chainfile) == 0*/) { @@ -645,7 +659,10 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) return -1; } + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_read_ahead (ssl_ctx, 0); + + rdev->ssl_accept_tmout = bnd->ssl_accept_tmout; #else rdev->stio->errnum = STIO_ENOIMPL; return -1; @@ -667,7 +684,7 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) rdev->localaddr = bnd->localaddr; #if defined(USE_SSL) - rdev->sslctx = ssl_ctx; + rdev->ssl_ctx = ssl_ctx; #endif return 0; @@ -680,7 +697,10 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) stio_scklen_t sl; stio_sckaddr_t localaddr; int x; - + #if defined(USE_SSL) + SSL_CTX* ssl_ctx = STIO_NULL; + SSL* ssl = STIO_NULL; + #endif if (!IS_STATEFUL(rdev)) { dev->stio->errnum = STIO_ENOCAPA; @@ -695,6 +715,18 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) return -1; } + if (conn->options & STIO_DEV_SCK_CONNECT_SSL) + { + #if defined(USE_SSL) + ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + if (!ssl_ctx) + { + rdev->stio->errnum = STIO_ESYSERR; + return -1; + } + #endif + } + /* the socket is already non-blocking */ x = connect (rdev->sck, sa, sl); if (x == -1) @@ -705,18 +737,18 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) { stio_tmrjob_t tmrjob; - if (!stio_isnegtime(&conn->tmout)) + if (stio_ispostime(&conn->tmout)) { STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob)); tmrjob.ctx = rdev; stio_gettime (&tmrjob.when); stio_addtime (&tmrjob.when, &conn->tmout, &tmrjob.when); tmrjob.handler = tmr_connect_handle; - tmrjob.idxptr = &rdev->tmridx_connect; + tmrjob.idxptr = &rdev->tmrjob_index; - STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID); - rdev->tmridx_connect = stio_instmrjob (rdev->stio, &tmrjob); - if (rdev->tmridx_connect == STIO_TMRIDX_INVALID) + STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID); + rdev->tmrjob_index = stio_instmrjob (rdev->stio, &tmrjob); + if (rdev->tmrjob_index == STIO_TMRIDX_INVALID) { stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN); /* event manipulation failure can't be handled properly. so ignore it. @@ -729,11 +761,29 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) rdev->remoteaddr = conn->remoteaddr; rdev->on_connect = conn->on_connect; rdev->on_disconnect = conn->on_disconnect; + #if defined(USE_SSL) + rdev->ssl_ctx = ssl_ctx; + #endif + + ssl = SSL_new (ssl_ctx); + if (!ssl) + { + } + + SSL_set_fd (ssl, rdev->sck); + + if (SSL_connect(ssl) <= 0) + { + } + return 0; } } rdev->stio->errnum = stio_syserrtoerrnum(errno); + #if defined(USE_SSL) + if (ssl_ctx) SSL_CTX_free (ssl_ctx); + #endif return -1; } @@ -742,9 +792,13 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) rdev->remoteaddr = conn->remoteaddr; rdev->on_connect = conn->on_connect; rdev->on_disconnect = conn->on_disconnect; + #if defined(USE_SSL) + rdev->ssl_ctx = ssl_ctx; + #endif sl = STIO_SIZEOF(localaddr); if (getsockname (rdev->sck, (struct sockaddr*)&localaddr, &sl) == 0) rdev->localaddr = localaddr; + return 0; } @@ -875,10 +929,10 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events) if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_RENEW, 0) <= -1) return -1; - if (rdev->tmridx_connect != STIO_TMRIDX_INVALID) + if (rdev->tmrjob_index != STIO_TMRIDX_INVALID) { - stio_deltmrjob (rdev->stio, rdev->tmridx_connect); - STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID); + stio_deltmrjob (rdev->stio, rdev->tmrjob_index); + STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID); } addrlen = STIO_SIZEOF(localaddr); @@ -946,7 +1000,7 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events) STIO_ASSERT (clidev->sck == clisck); clidev->dev_capa |= STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | STIO_DEV_CAPA_STREAM | STIO_DEV_CAPA_OUT_QUEUED; - if (rdev->sslctx) + if (rdev->ssl_ctx) clidev->state |= STIO_DEV_SCK_ACCEPTING_SSL; else clidev->state |= STIO_DEV_SCK_ACCEPTED; @@ -1000,24 +1054,42 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events) clidev->on_write = rdev->on_write; clidev->on_read = rdev->on_read; + STIO_ASSERT (clidev->tmrjob_index == STIO_TMRIDX_INVALID); + if (clidev->state & STIO_DEV_SCK_ACCEPTED) { STIO_ASSERT (!(clidev->state & STIO_DEV_SCK_ACCEPTING_SSL)); - clidev->tmridx_connect = STIO_TMRIDX_INVALID; if (clidev->on_connect(clidev) <= -1) stio_dev_sck_halt (clidev); } else { + + STIO_ASSERT (clidev->state & STIO_DEV_SCK_ACCEPTING_SSL); /* actual SSL acceptance must be completed in the client device */ /* let the client device know the SSL context to use */ - clidev->sslctx = rdev->sslctx; + clidev->ssl_ctx = rdev->ssl_ctx; -/* TODO: secure accept timeout handling */ - /* clidev->tmridx_connect??? */ - clidev->tmridx_connect = STIO_TMRIDX_INVALID; -printf ("TO DO SSL ...............................\n"); + if (stio_ispostime(&rdev->ssl_accept_tmout)) + { + stio_tmrjob_t tmrjob; + + STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob)); + tmrjob.ctx = clidev; + stio_gettime (&tmrjob.when); + stio_addtime (&tmrjob.when, &rdev->ssl_accept_tmout, &tmrjob.when); + + tmrjob.handler = ssl_accept_timedout; + tmrjob.idxptr = &clidev->tmrjob_index; + + clidev->tmrjob_index = stio_instmrjob (clidev->stio, &tmrjob); + if (clidev->tmrjob_index == STIO_TMRIDX_INVALID) + { + /* TODO: call a warning callback */ + printf ("SSL ACCEPT TIMEOUT CAN't BE HONORED....\n"); + } + } } return 0; /* success but don't invoke on_read() */ @@ -1035,7 +1107,7 @@ printf ("SSL IN ACCPEING>.. %p.......................\n", rdev); SSL* ssl; printf ("SSL CREATED.....................\n"); - ssl = SSL_new (rdev->sslctx); + ssl = SSL_new (rdev->ssl_ctx); if (!ssl) { printf ("SSL ERROR 1>..................... %s\n", ERR_reason_error_string(ERR_get_error())); @@ -1070,6 +1142,12 @@ printf ("SSL ERROR 3>..................... %s\n", ERR_reason_error_string(err)); } printf ("SSL ACCEPTED.....................\n"); + if (rdev->tmrjob_index != STIO_TMRIDX_INVALID) + { + stio_deltmrjob (rdev->stio, rdev->tmrjob_index); + rdev->tmrjob_index = STIO_TMRIDX_INVALID; + } + rdev->state &= ~STIO_DEV_SCK_ACCEPTING_SSL; rdev->state |= STIO_DEV_SCK_ACCEPTED; if (rdev->on_connect(rdev) <= -1) stio_dev_sck_halt (rdev); diff --git a/stio/lib/stio-sck.h b/stio/lib/stio-sck.h index f3d652a..36b8c9e 100644 --- a/stio/lib/stio-sck.h +++ b/stio/lib/stio-sck.h @@ -164,13 +164,22 @@ struct stio_dev_sck_bind_t stio_sckaddr_t localaddr; /* TODO: add device name for BIND_TO_DEVICE */ - const stio_mchar_t* certfile; - const stio_mchar_t* keyfile; + const stio_mchar_t* ssl_certfile; + const stio_mchar_t* ssl_keyfile; + stio_ntime_t ssl_accept_tmout; }; +enum stio_def_sck_connect_option_t +{ + STIO_DEV_SCK_CONNECT_SSL = (1 << 15) +}; +typedef enum stio_dev_sck_connect_option_t stio_dev_sck_connect_option_t; + + typedef struct stio_dev_sck_connect_t stio_dev_sck_connect_t; struct stio_dev_sck_connect_t { + int options; stio_sckaddr_t remoteaddr; stio_ntime_t tmout; /* connect timeout */ stio_dev_sck_on_connect_t on_connect; @@ -188,9 +197,9 @@ struct stio_dev_sck_listen_t typedef struct stio_dev_sck_accept_t stio_dev_sck_accept_t; struct stio_dev_sck_accept_t { - stio_syshnd_t sck; + stio_syshnd_t sck; /* TODO: add timeout */ - stio_sckaddr_t remoteaddr; + stio_sckaddr_t remoteaddr; }; struct stio_dev_sck_t @@ -200,23 +209,15 @@ struct stio_dev_sck_t stio_dev_sck_type_t type; stio_sckhnd_t sck; - void* sslctx; + void* ssl_ctx; void* ssl; - - stio_dev_sck_on_write_t on_write; - stio_dev_sck_on_read_t on_read; + stio_ntime_t ssl_accept_tmout; int state; - /* return 0 on succes, -1 on failure. - * called on a new tcp device for an accepted client or - * on a tcp device conntected to a remote server */ - stio_dev_sck_on_connect_t on_connect; - stio_dev_sck_on_disconnect_t on_disconnect; - stio_tmridx_t tmridx_connect; - - /* peer address for a stateful stream socket. valid if one of the + /* remote peer address for a stateful stream socket. valid if one of the * followings is set in state: + * STIO_DEV_TCP_ACCEPTING_SSL * STIO_DEV_TCP_ACCEPTED * STIO_DEV_TCP_CONNECTED * STIO_DEV_TCP_CONNECTING @@ -225,8 +226,25 @@ struct stio_dev_sck_t * a stateless socket */ stio_sckaddr_t remoteaddr; + /* local socket address */ stio_sckaddr_t localaddr; + + /* original destination address */ stio_sckaddr_t orgdstaddr; + + stio_dev_sck_on_write_t on_write; + stio_dev_sck_on_read_t on_read; + + /* return 0 on succes, -1 on failure. + * called on a new tcp device for an accepted client or + * on a tcp device conntected to a remote server */ + stio_dev_sck_on_connect_t on_connect; + stio_dev_sck_on_disconnect_t on_disconnect; + + /* timer job index for handling + * - connect() timeout for a connecting socket. + * - SSL_accept() timeout for a socket accepting SSL */ + stio_tmridx_t tmrjob_index; }; #ifdef __cplusplus diff --git a/stio/lib/stio.c b/stio/lib/stio.c index 55998c0..98dc61d 100644 --- a/stio/lib/stio.c +++ b/stio/lib/stio.c @@ -1045,7 +1045,7 @@ enqueue_data: q->olen = len; STIO_MEMCPY (q->ptr, uptr, urem); - if (tmout && !stio_isnegtime(tmout)) + if (tmout && stio_ispostime(tmout)) { stio_tmrjob_t tmrjob; @@ -1060,7 +1060,6 @@ enqueue_data: if (q->tmridx == STIO_TMRIDX_INVALID) { STIO_MMGR_FREE (dev->stio->mmgr, q); -printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz222222\n"); return -1; } } @@ -1073,7 +1072,6 @@ printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz222222\n"); { unlink_wq (dev->stio, q); STIO_MMGR_FREE (dev->stio->mmgr, q); -printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz11111\n"); return -1; } } @@ -1082,7 +1080,6 @@ printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz11111\n"); dev->stio->renew_watch = 1; } -printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz\n"); return 0; /* request pused to a write queue. */ } diff --git a/stio/lib/stio.h b/stio/lib/stio.h index a603d23..8abd2ff 100644 --- a/stio/lib/stio.h +++ b/stio/lib/stio.h @@ -512,6 +512,9 @@ STIO_EXPORT void stio_dev_halt ( /* if time has been normalized properly, nsec must be equal to or * greater than 0. */ #define stio_isnegtime(x) ((x)->sec < 0) +#define stio_ispostime(x) ((x)->sec > 0 || ((x)->sec == 0 && (x)->nsec > 0)) +#define stio_iszerotime(x) ((x)->sec == 0 && (x)->nsec == 0) + /** * The stio_gettime() function gets the current time.