Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tls and http apis for post handshake #713

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/re_http.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,19 +179,31 @@ int http_client_set_tls_max_version(struct http_cli *cli, int version);
struct http_sock;
struct http_conn;

enum re_https_verify_msg {
HTTPS_MSG_OK = 0,
HTTPS_MSG_REQUEST_CERT = 1,
HTTPS_MSG_IGNORE = 2,
};

typedef void (http_req_h)(struct http_conn *conn, const struct http_msg *msg,
void *arg);
typedef enum re_https_verify_msg (https_verify_msg_h)(struct http_conn *conn,
const struct http_msg *msg, void *arg);

int http_listen_fd(struct http_sock **sockp, re_sock_t fd, http_req_h *reqh,
void *arg);
int http_listen(struct http_sock **sockp, const struct sa *laddr,
http_req_h *reqh, void *arg);
int https_listen(struct http_sock **sockp, const struct sa *laddr,
const char *cert, http_req_h *reqh, void *arg);
int https_set_verify_msgh(struct http_sock *sock,
https_verify_msg_h *verifyh);
struct tcp_sock *http_sock_tcp(struct http_sock *sock);
struct tls *http_sock_tls(const struct http_sock *conn);
const struct sa *http_conn_peer(const struct http_conn *conn);
struct tcp_conn *http_conn_tcp(struct http_conn *conn);
struct tls_conn *http_conn_tls(struct http_conn *conn);

void http_conn_reset_timeout(struct http_conn *conn);
void http_conn_close(struct http_conn *conn);
int http_reply(struct http_conn *conn, uint16_t scode, const char *reason,
Expand Down
11 changes: 11 additions & 0 deletions include/re_tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ enum tls_keytype {
TLS_KEYTYPE_EC,
};

struct tls_conn_d {
int (*verifyh) (int ok, void *arg);
void *arg;
};

int tls_alloc(struct tls **tlsp, enum tls_method method, const char *keyfile,
const char *pwd);
Expand All @@ -46,6 +50,10 @@ int tls_set_certificate_der(struct tls *tls, enum tls_keytype keytype,
const uint8_t *key, size_t len_key);
int tls_set_certificate(struct tls *tls, const char *cert, size_t len);
void tls_set_verify_client(struct tls *tls);
void tls_set_verify_client_trust_all(struct tls *tls);
int tls_set_verify_client_handler(struct tls_conn *tc, int depth,
int (*verifyh) (int ok, void *arg), void *arg);

int tls_set_srtp(struct tls *tls, const char *suites);
int tls_fingerprint(const struct tls *tls, enum tls_fingerprint type,
uint8_t *md, size_t size);
Expand Down Expand Up @@ -74,13 +82,16 @@ bool tls_get_session_reuse(const struct tls_conn *tc);
int tls_reuse_session(const struct tls_conn *tc);
bool tls_session_reused(const struct tls_conn *tc);
int tls_update_sessions(const struct tls_conn *tc);
void tls_set_posthandshake_auth(struct tls *tls, int enabled);

/* TCP */

int tls_conn_change_cert(struct tls_conn *tc, const char *file);
int tls_start_tcp(struct tls_conn **ptc, struct tls *tls,
struct tcp_conn *tcp, int layer);

int tls_verify_client_post_handshake(struct tls_conn *tc);

const struct tcp_conn *tls_get_tcp_conn(const struct tls_conn *tc);


Expand Down
149 changes: 146 additions & 3 deletions src/http/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright (C) 2011 Creytiv.com
*/

#include <string.h>
#include <re_types.h>
#include <re_mem.h>
#include <re_mbuf.h>
Expand All @@ -29,6 +30,7 @@ struct http_sock {
struct tcp_sock *ts;
struct tls *tls;
http_req_h *reqh;
https_verify_msg_h *verifyh;
void *arg;
};

Expand All @@ -40,6 +42,7 @@ struct http_conn {
struct tcp_conn *tc;
struct tls_conn *sc;
struct mbuf *mb;
struct tmr verify_cert_tmr;
};


Expand Down Expand Up @@ -97,6 +100,106 @@ static void timeout_handler(void *arg)
}


struct http_verify_msg_d {
struct http_conn *conn;
struct http_msg *msg;
int err;
int scode;
const char *reason;
};


static void verify_msg_destructor(void *arg)
{
struct http_verify_msg_d *d = arg;
mem_deref(d->msg);
}


static void verify_cert_done(void *arg)
{
struct http_verify_msg_d *d = arg;

if (d->err)
http_ereply(d->conn, d->scode, d->reason);
else
d->conn->sock->reqh(d->conn, d->msg, d->conn->sock->arg);

mem_deref(arg);
}


static int http_verify_handler(int ok, void *arg)
{
struct http_verify_msg_d *d = arg;

if (ok) {
d->err = 0;
}
else {
d->err = EACCES;
d->scode = 403;
d->reason = "Forbidden";
}

tmr_start(&d->conn->verify_cert_tmr, 1, verify_cert_done, d);

return ok;
}


static enum re_https_verify_msg verify_msg(struct http_conn *conn,
struct http_msg *msg)
{
int err;
enum re_https_verify_msg res;
struct http_verify_msg_d *d;

if (!conn->sock)
return HTTPS_MSG_IGNORE;
else if (!conn->sock->verifyh)
return HTTPS_MSG_OK;

res = conn->sock->verifyh(conn, msg, conn->sock->arg);

if (res == HTTPS_MSG_REQUEST_CERT) {

d = mem_zalloc(sizeof(*conn), verify_msg_destructor);
if (!d) {
res = HTTPS_MSG_IGNORE;
goto out;
}

d->conn = conn;
d->err = ETIMEDOUT;
d->scode = 408;
d->reason = "Request Timeout";
d->msg = msg;

tmr_init(&conn->verify_cert_tmr);
tmr_start(&conn->verify_cert_tmr, TIMEOUT_IDLE,
verify_cert_done, d);

err = tls_set_verify_client_handler(http_conn_tls(conn),
-1, http_verify_handler, d);
if (err) {
res = HTTPS_MSG_IGNORE;
goto out;
}

err = tls_verify_client_post_handshake(
http_conn_tls(conn));
if (err) {
res = HTTPS_MSG_IGNORE;
goto out;
}
}

out:
return res;
}


static void recv_handler(struct mbuf *mb, void *arg)
{
struct http_conn *conn = arg;
Expand Down Expand Up @@ -171,10 +274,10 @@ static void recv_handler(struct mbuf *mb, void *arg)
conn->mb = mem_deref(conn->mb);
}

if (conn->sock)
if (verify_msg(conn, msg) == HTTPS_MSG_OK) {
conn->sock->reqh(conn, msg, conn->sock->arg);

mem_deref(msg);
mem_deref(msg);
}

if (!conn->tc) {
err = ENOTCONN;
Expand Down Expand Up @@ -363,6 +466,33 @@ int https_listen(struct http_sock **sockp, const struct sa *laddr,
}


/**
* Set verify http msg handler.
*
* This handler allows to decide whether e.g. a certificate
* should be requested from the client or not.
* E.g. This decision can done based on the http path contained in
* struct http_msg.
*
* @param sock HTTP socket
* @param verifyh Verify handler called before the https request
* handler is called to return a http response
* to the client.
*
* @return 0 if success, otherwise errorcode
*/
int https_set_verify_msgh(struct http_sock *sock,
https_verify_msg_h *verifyh)
{
if (!sock || !verifyh)
return EINVAL;

sock->verifyh = verifyh;

return 0;
}


/**
* Get the TCP socket of an HTTP socket
*
Expand All @@ -376,6 +506,19 @@ struct tcp_sock *http_sock_tcp(struct http_sock *sock)
}


/**
* Get the TLS struct of an HTTP sock
*
* @param conn HTTP connection
*
* @return TLS struct
*/
struct tls *http_sock_tls(const struct http_sock *sock)
{
return sock ? sock->tls : NULL;
}


/**
* Get the peer address of an HTTP connection
*
Expand Down
Loading