Add initial SSL stuff + bare bones NPN advertisement. So far chrome connects and

shows our connection as SPDY/3, good start.
This commit is contained in:
Joris Vink 2013-04-21 20:21:46 +02:00
parent cba9628f16
commit 68d0523817
4 changed files with 114 additions and 3 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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. */;
}
}
@ -92,6 +102,37 @@ main(int argc, char *argv[])
return (0);
}
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)
{
@ -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);
}

View File

@ -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>