ocserv: added '/ca.pem' and '/ca.cer' HTTP handler

This handler will return the server's CA certificate to the requester
in PEM and DER formats.
This commit is contained in:
Nikos Mavrogiannopoulos
2016-05-17 14:42:03 +02:00
parent edabd11b4a
commit f87871fc48
3 changed files with 105 additions and 1 deletions

View File

@@ -101,7 +101,6 @@ int get_cert_handler(worker_st * ws, unsigned http_ver)
return -1;
}
}
int get_cert_der_handler(worker_st * ws, unsigned http_ver)
{
if (ws->conn_type != SOCK_TYPE_UNIX) { /* we have TLS */
@@ -120,6 +119,107 @@ int get_cert_der_handler(worker_st * ws, unsigned http_ver)
}
}
static
int ca_handler(worker_st * ws, unsigned http_ver, unsigned der)
{
#if GNUTLS_VERSION_NUMBER < 0x030205
return -1;
#else
if (ws->conn_type != SOCK_TYPE_UNIX) { /* we have TLS */
const gnutls_datum_t *certs;
gnutls_datum_t out = {NULL, 0}, tmpca;
unsigned i;
int ret;
gnutls_x509_crt_t issuer = NULL, crt = NULL;
oclog(ws, LOG_DEBUG, "requested server CA");
certs = gnutls_certificate_get_ours(ws->session);
if (certs == NULL) {
oclog(ws, LOG_DEBUG, "could not obtain our cert");
return -1;
}
ret = gnutls_x509_crt_init(&crt);
if (ret < 0) {
oclog(ws, LOG_DEBUG, "could not initialize cert");
return -1;
}
ret = gnutls_x509_crt_init(&issuer);
if (ret < 0) {
oclog(ws, LOG_DEBUG, "could not initialize cert");
ret = -1;
goto cleanup;
}
ret = gnutls_x509_crt_import(crt, &certs[0], GNUTLS_X509_FMT_DER);
if (ret < 0) {
ret = -1;
oclog(ws, LOG_DEBUG, "could not import our cert");
goto cleanup;
}
for (i=0;i<8;i++) {
ret = gnutls_certificate_get_crt_raw(ws->creds->xcred, i, 1, &tmpca);
if (ret < 0) {
goto cleanup;
}
ret = gnutls_x509_crt_import(issuer, &tmpca, GNUTLS_X509_FMT_DER);
if (ret < 0) {
ret = -1;
oclog(ws, LOG_DEBUG, "could not import issuer cert");
goto cleanup;
}
ret = gnutls_x509_crt_check_issuer(crt, issuer);
if (ret != 0) {
ret = gnutls_x509_crt_export2(issuer, der?GNUTLS_X509_FMT_DER:GNUTLS_X509_FMT_PEM, &out);
if (ret < 0) {
ret = -1;
oclog(ws, LOG_DEBUG, "could not export issuer of cert");
goto cleanup;
}
break;
}
gnutls_x509_crt_deinit(issuer);
issuer = NULL;
}
ret = send_data(ws, http_ver, "application/pkix-cert", (char*)out.data, out.size);
cleanup:
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
oclog(ws, LOG_DEBUG, "could not get CA; does the server cert list contain the CA certificate?");
ret = -1;
}
if (crt)
gnutls_x509_crt_deinit(crt);
if (issuer)
gnutls_x509_crt_deinit(issuer);
gnutls_free(out.data);
return ret;
} else {
return -1;
}
#endif
}
int get_ca_handler(worker_st * ws, unsigned http_ver)
{
return ca_handler(ws, http_ver, 0);
}
int get_ca_der_handler(worker_st * ws, unsigned http_ver)
{
return ca_handler(ws, http_ver, 1);
}
#ifdef ANYCONNECT_CLIENT_COMPAT
int get_config_handler(worker_st *ws, unsigned http_ver)
{

View File

@@ -58,6 +58,8 @@ const static struct known_urls_st known_urls[] = {
LL("/VPN", get_auth_handler, post_auth_handler),
LL("/cert.pem", get_cert_handler, NULL),
LL("/cert.cer", get_cert_der_handler, NULL),
LL("/ca.pem", get_ca_handler, NULL),
LL("/ca.cer", get_ca_der_handler, NULL),
#ifdef ANYCONNECT_CLIENT_COMPAT
LL("/1/index.html", get_empty_handler, NULL),
LL("/1/Linux", get_empty_handler, NULL),

View File

@@ -291,6 +291,8 @@ int post_auth_handler(worker_st *server, unsigned http_ver);
int post_kkdcp_handler(worker_st *server, unsigned http_ver);
int get_cert_handler(worker_st * ws, unsigned http_ver);
int get_cert_der_handler(worker_st * ws, unsigned http_ver);
int get_ca_handler(worker_st * ws, unsigned http_ver);
int get_ca_der_handler(worker_st * ws, unsigned http_ver);
int response_404(worker_st *ws, unsigned http_ver);
int get_empty_handler(worker_st *server, unsigned http_ver);