kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 68d0523817537f46783aaf1bc61a10da2fc9af74
parent cba9628f16ad49bc7b8bb2f4077f16978b1cb9fb
Author: Joris Vink <joris@coders.se>
Date:   Sun, 21 Apr 2013 20:21:46 +0200

Add initial SSL stuff + bare bones NPN advertisement. So far chrome connects and
shows our connection as SPDY/3, good start.

Diffstat:
Makefile | 4++--
includes/kore.h | 9+++++++++
src/kore.c | 100++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/utils.c | 4++++
4 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,6 +1,6 @@ # Kore Makefile -CC=clang +CC=gcc BIN=kore S_SRC= src/kore.c src/utils.c @@ -9,7 +9,7 @@ S_OBJS= $(S_SRC:.c=.o) CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+=-Wsign-compare -Iincludes -g -LDFLAGS= +LDFLAGS=-lcrypto -lssl light: $(S_OBJS) $(CC) $(CFLAGS) $(LDFLAGS) $(S_OBJS) -o $(BIN) diff --git a/includes/kore.h b/includes/kore.h @@ -21,9 +21,12 @@ #define KORE_RESULT_OK 1 #define errno_s strerror(errno) +#define ssl_errno_s ERR_error_string(ERR_get_error(), NULL) #define kore_log(fmt, ...) \ kore_log_internal(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define KORE_SSL_PROTO_STRING "\x06spdy/3\x08http/1.1" + struct netbuf { u_int8_t *data; u_int32_t offset; @@ -39,10 +42,16 @@ struct listener { struct sockaddr_in sin; }; +#define CONN_STATE_UNKNOWN 0 +#define CONN_STATE_SSL_SHAKE 1 +#define CONN_STATE_ESTABLISHED 2 + struct connection { int fd; + int state; struct sockaddr_in sin; void *owner; + SSL *ssl; TAILQ_HEAD(, netbuf) send_queue; TAILQ_HEAD(, netbuf) recv_queue; diff --git a/src/kore.c b/src/kore.c @@ -23,6 +23,9 @@ #include <netinet/in.h> #include <arpa/inet.h> +#include <openssl/err.h> +#include <openssl/ssl.h> + #include <errno.h> #include <fcntl.h> #include <stdio.h> @@ -35,12 +38,16 @@ #define EPOLL_EVENTS 500 static int efd = -1; +static SSL_CTX *ssl_ctx = NULL; +static int kore_server_sslstart(void); static int kore_server_bind(struct listener *, const char *, int); static int kore_server_accept(struct listener *); static int kore_connection_handle(struct connection *, int); static int kore_socket_nonblock(int); static void kore_event(int, int, void *); +static int kore_ssl_npn_cb(SSL *, const unsigned char **, + unsigned int *, void *); int main(int argc, char *argv[]) @@ -55,6 +62,8 @@ main(int argc, char *argv[]) if (!kore_server_bind(&server, argv[1], atoi(argv[2]))) fatal("cannot bind to %s:%s", argv[1], argv[2]); + if (!kore_server_sslstart()) + fatal("cannot initiate SSL"); if ((efd = epoll_create(1000)) == -1) fatal("epoll_create(): %s", errno_s); @@ -82,7 +91,8 @@ main(int argc, char *argv[]) kore_server_accept(&server); } else { c = (struct connection *)events[i].data.ptr; - if (!kore_connection_handle(c, events[i].events)) + if (!kore_connection_handle(c, + events[i].events)) /* Disconnect. */; } } @@ -93,6 +103,37 @@ main(int argc, char *argv[]) } static int +kore_server_sslstart(void) +{ + SSL_library_init(); + SSL_load_error_strings(); + ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + if (ssl_ctx == NULL) { + kore_log("SSL_ctx_new(): %s", ssl_errno_s); + return (KORE_RESULT_ERROR); + } + + if (!SSL_CTX_use_certificate_file(ssl_ctx, "cert/server.crt", + SSL_FILETYPE_PEM)) { + kore_log("SSL_CTX_use_certificate_file(): %s", ssl_errno_s); + return (KORE_RESULT_ERROR); + } + + if (!SSL_CTX_use_PrivateKey_file(ssl_ctx, "cert/server.key", + SSL_FILETYPE_PEM)) { + kore_log("SSL_CTX_use_PrivateKey_file(): %s", ssl_errno_s); + return (KORE_RESULT_ERROR); + } + + SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); + SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, kore_ssl_npn_cb, NULL); + + return (KORE_RESULT_OK); +} + +static int kore_server_bind(struct listener *l, const char *ip, int port) { if ((l->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { @@ -146,6 +187,8 @@ kore_server_accept(struct listener *l) } c->owner = l; + c->ssl = NULL; + c->state = CONN_STATE_SSL_SHAKE; TAILQ_INIT(&(c->send_queue)); TAILQ_INIT(&(c->recv_queue)); kore_event(c->fd, EPOLLIN | EPOLLET, c); @@ -157,6 +200,49 @@ kore_server_accept(struct listener *l) static int kore_connection_handle(struct connection *c, int flags) { + int r; + + switch (c->state) { + case CONN_STATE_SSL_SHAKE: + if (c->ssl == NULL) { + c->ssl = SSL_new(ssl_ctx); + if (c->ssl == NULL) { + kore_log("SSL_new(): %s", ssl_errno_s); + return (KORE_RESULT_ERROR); + } + + SSL_set_fd(c->ssl, c->fd); + } + + r = SSL_accept(c->ssl); + if (r <= 0) { + r = SSL_get_error(c->ssl, r); + switch (r) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + return (KORE_RESULT_OK); + default: + kore_log("SSL_accept(): %s", ssl_errno_s); + return (KORE_RESULT_ERROR); + } + } + + r = SSL_get_verify_result(c->ssl); + if (r != X509_V_OK) { + kore_log("SSL_get_verify_result(): %s", ssl_errno_s); + return (KORE_RESULT_ERROR); + } + + c->state = CONN_STATE_ESTABLISHED; + break; + case CONN_STATE_ESTABLISHED: + kore_log("got bytes on established"); + break; + default: + kore_log("unknown state on %d (%d)", c->fd, c->state); + break; + } + return (KORE_RESULT_OK); } @@ -189,3 +275,15 @@ kore_event(int fd, int flags, void *udata) if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &evt) == -1) fatal("epoll_ctl(): %s", errno_s); } + +static int +kore_ssl_npn_cb(SSL *ssl, const unsigned char **data, + unsigned int *len, void *arg) +{ + kore_log("npn callback: sending protocols"); + + *data = (const unsigned char *)KORE_SSL_PROTO_STRING; + *len = strlen(KORE_SSL_PROTO_STRING); + + return (SSL_TLSEXT_ERR_OK); +} diff --git a/src/utils.c b/src/utils.c @@ -22,8 +22,12 @@ #include <netinet/in.h> #include <arpa/inet.h> +#include <openssl/err.h> +#include <openssl/ssl.h> + #include <errno.h> #include <fcntl.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h>