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

tls, http: allow the http client to check server certificates hostname and purpose #10

Merged
merged 4 commits into from
Aug 23, 2020
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
3 changes: 3 additions & 0 deletions include/re_http.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ typedef void (http_conn_h)(struct tcp_conn *tc, struct tls_conn *sc,
void *arg);

int http_client_alloc(struct http_cli **clip, struct dnsc *dnsc);
int http_client_add_ca(struct http_cli *cli, const char *tls_ca);
int http_client_set_tls_hostname(struct http_cli *cli,
const struct pl *hostname);
int http_request(struct http_req **reqp, struct http_cli *cli, const char *met,
const char *uri, http_resp_h *resph, http_data_h *datah,
void *arg, const char *fmt, ...);
Expand Down
3 changes: 3 additions & 0 deletions include/re_tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ int tls_fingerprint(const struct tls *tls, enum tls_fingerprint type,
int tls_peer_fingerprint(const struct tls_conn *tc, enum tls_fingerprint type,
uint8_t *md, size_t size);
int tls_peer_common_name(const struct tls_conn *tc, char *cn, size_t size);
int tls_peer_set_verify_host(struct tls_conn *tc, const char *hostname);
int tls_set_verify_purpose(struct tls *tls, const char *purpose);
int tls_set_hostname(char *tls_hostname, const struct pl *hostname);
int tls_peer_verify(const struct tls_conn *tc);
int tls_srtp_keyinfo(const struct tls_conn *tc, enum srtp_suite *suite,
uint8_t *cli_key, size_t cli_key_size,
Expand Down
58 changes: 56 additions & 2 deletions src/http/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct http_cli {
struct hash *ht_conn;
struct dnsc *dnsc;
struct tls *tls;
char *tls_hostname;
};

struct conn;
Expand Down Expand Up @@ -97,6 +98,7 @@ static void cli_destructor(void *arg)
mem_deref(cli->ht_conn);
mem_deref(cli->dnsc);
mem_deref(cli->tls);
mem_deref(cli->tls_hostname);
}


Expand Down Expand Up @@ -442,6 +444,17 @@ static int conn_connect(struct http_req *req)
err = tls_start_tcp(&conn->sc, req->cli->tls, conn->tc, 0);
if (err)
goto out;

if (req->cli->tls_hostname)
err = tls_peer_set_verify_host(conn->sc,
req->cli->tls_hostname);

if (err)
goto out;

err = tls_set_servername(conn->sc, req->host);
if (err)
goto out;
}
#endif

Expand Down Expand Up @@ -683,11 +696,15 @@ int http_client_alloc(struct http_cli **clip, struct dnsc *dnsc)

#ifdef USE_TLS
err = tls_alloc(&cli->tls, TLS_METHOD_SSLV23, NULL, NULL);
if (err)
goto out;

err = tls_set_verify_purpose(cli->tls, "sslserver");
if (err)
goto out;
#else
err = 0;
#endif
if (err)
goto out;

cli->dnsc = mem_ref(dnsc);

Expand All @@ -699,3 +716,40 @@ int http_client_alloc(struct http_cli **clip, struct dnsc *dnsc)

return err;
}


#ifdef USE_TLS
/**
* Add trusted CA certificates
*
* @param cli HTTP client
* @param capath Path to CA certificates
*
* @return 0 if success, otherwise errorcode
*/
int http_client_add_ca(struct http_cli *cli, const char *tls_ca)
{
if (!cli || !tls_ca)
return EINVAL;

return tls_add_ca(cli->tls, tls_ca);
}


/**
* Set verify host name
*
* @param cli HTTP client
* @param hostname String for alternative name validation.
*
* @return 0 if success, otherwise errorcode
*/
int http_client_set_tls_hostname(struct http_cli *cli,
const struct pl *hostname)
{
if (!cli || !hostname)
return EINVAL;

return tls_set_hostname(cli->tls_hostname, hostname);
}
#endif
84 changes: 84 additions & 0 deletions src/tls/openssl/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,90 @@ int tls_add_ca(struct tls *tls, const char *cafile)
}


/**
* Set SSL verification of the certificate purpose
*
* @param tls TLS Context
* @param purpose Certificate purpose as string
*
* @return int 0 if success, errorcode otherwise
*/
int tls_set_verify_purpose(struct tls *tls, const char *purpose)
{
int err;
int i;
X509_PURPOSE *xptmp;

if (!tls || !purpose)
return EINVAL;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
i = X509_PURPOSE_get_by_sname(purpose);
#else
i = X509_PURPOSE_get_by_sname((char *) purpose);
#endif

if (i < 0)
return EINVAL;

/* purpose index -> purpose object */
/* purpose object -> purpose value */
xptmp = X509_PURPOSE_get0(i);
i = X509_PURPOSE_get_id(xptmp);
err = SSL_CTX_set_purpose(tls->ctx, i);

return err == 1 ? 0 : EINVAL;
}


/**
* Set SSL verification of hostname
*
* @param tc TLS Connection
* @param hostname Certificate hostname
*
* @return int 0 if success, errorcode otherwise
*/
int tls_peer_set_verify_host(struct tls_conn *tc, const char *hostname)
{
int err = 0;

if (!tc)
return EINVAL;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
err = SSL_set1_host(tc->ssl, hostname);
#else
DEBUG_WARNING("verify hostname needs openssl version 1.1.0\n");
return ENOSYS;
#endif

return err == 1 ? 0 : EINVAL;
}


/**
* Convert string hostname to pl hostname
*
* @param tls_hostname Certificate hostname as string
* @param hostname Certificate hostname as pl
*
* @return int 0 if success, errorcode otherwise
*/
int tls_set_hostname(char *tls_hostname, const struct pl *hostname)
{
if (!tls_hostname || !hostname)
return EINVAL;

#if OPENSSL_VERSION_NUMBER < 0x10100000L
DEBUG_WARNING("verify hostname needs openssl version 1.1.0\n");
return ENOSYS;
#endif

return pl_strdup(&tls_hostname, hostname);
}


/**
* Generate and set selfsigned certificate on TLS context
*
Expand Down