Improvements for client certificates.

Double check we actually get a certificate if we are asking for one.
Even though we set SSL_VERIFY_FAIL_IF_NO_PEER_CERT it's a sane thing to do.

Start logging the CN for the received client certificate in the access logs.

As a bonus re-arrange some accesslog stuff for sanity.
This commit is contained in:
Joris Vink 2014-03-05 11:38:47 +01:00
parent 75c4bb0754
commit 1375190936
3 changed files with 64 additions and 12 deletions

View File

@ -66,6 +66,12 @@
#define NETBUF_CALL_CB_ALWAYS 0x01
#define NETBUF_FORCE_REMOVE 0x02
#define X509_GET_CN(c, o, l) \
X509_NAME_get_text_by_NID(X509_get_subject_name(c), \
NID_commonName, o, l)
#define X509_CN_LENGTH (ub_common_name + 1)
/* XXX hackish. */
struct http_request;
struct spdy_stream;
@ -135,6 +141,7 @@ struct connection {
SSL *ssl;
u_int8_t flags;
void *hdlr_extra;
X509 *cert;
u_int8_t addrtype;
union {

View File

@ -34,6 +34,7 @@ struct kore_log_packet {
char host[KORE_DOMAINNAME_LEN];
char path[HTTP_URI_LEN];
char agent[HTTP_USERAGENT_LEN];
char cn[X509_CN_LENGTH];
};
void
@ -55,13 +56,12 @@ kore_accesslog_wait(void)
{
ssize_t len;
time_t now;
size_t slen;
int nfds;
struct kore_domain *dom;
struct pollfd pfd[1];
int nfds, l;
struct kore_log_packet logpacket;
char addr[INET6_ADDRSTRLEN];
char *method, buf[4096], *tbuf;
char *method, *buf, *tbuf, *cn;
pfd[0].fd = accesslog_fd[0];
pfd[0].events = POLLIN;
@ -94,10 +94,22 @@ kore_accesslog_wait(void)
return (KORE_RESULT_OK);
}
if (logpacket.method == HTTP_METHOD_GET)
switch (logpacket.method) {
case HTTP_METHOD_GET:
method = "GET";
else
break;
case HTTP_METHOD_POST:
method = "POST";
break;
default:
method = "UNKNOWN";
break;
}
if (logpacket.cn[0] != '\0')
cn = logpacket.cn;
else
cn = "none";
if (inet_ntop(logpacket.addrtype, &(logpacket.addr),
addr, sizeof(addr)) == NULL)
@ -105,20 +117,25 @@ kore_accesslog_wait(void)
time(&now);
tbuf = kore_time_to_date(now);
snprintf(buf, sizeof(buf), "[%s] %s %d %s %s (w#%d) (%dms) (%s)\n",
tbuf, addr, logpacket.status, method,
logpacket.path, logpacket.worker_id, logpacket.time_req,
logpacket.agent);
slen = strlen(buf);
l = asprintf(&buf, "[%s] %s %d %s %s (w#%d) (%dms) (%s) (%s)\n",
tbuf, addr, logpacket.status, method, logpacket.path,
logpacket.worker_id, logpacket.time_req, cn, logpacket.agent);
if (l == -1) {
kore_log(LOG_WARNING,
"kore_accesslog_wait(): asprintf() == -1");
return (KORE_RESULT_ERROR);
}
len = write(dom->accesslog, buf, l);
free(buf);
len = write(dom->accesslog, buf, slen);
if (len == -1) {
kore_log(LOG_WARNING,
"kore_accesslog_wait(): write(): %s", errno_s);
return (KORE_RESULT_ERROR);
}
if ((size_t)len != slen)
if (len != l)
kore_log(LOG_NOTICE, "accesslog: %s", buf);
return (KORE_RESULT_OK);
@ -157,6 +174,14 @@ kore_accesslog(struct http_request *req)
sizeof(logpacket.agent));
}
memset(logpacket.cn, '\0', sizeof(logpacket.cn));
if (req->owner->cert != NULL) {
if (X509_GET_CN(req->owner->cert,
logpacket.cn, sizeof(logpacket.cn)) == -1) {
kore_log(LOG_WARNING, "client cert without a CN?");
}
}
len = send(accesslog_fd[1], &logpacket, sizeof(logpacket), 0);
if (len == -1) {
kore_log(LOG_WARNING, "kore_accesslog(): send(): %s", errno_s);

View File

@ -70,6 +70,7 @@ kore_connection_accept(struct listener *l, struct connection **out)
c->owner = l;
c->ssl = NULL;
c->flags = 0;
c->cert = NULL;
c->hdlr_extra = NULL;
c->inflate_started = 0;
c->deflate_started = 0;
@ -108,6 +109,7 @@ kore_connection_handle(struct connection *c)
int r;
u_int32_t len;
const u_char *data;
char cn[X509_CN_LENGTH];
kore_debug("kore_connection_handle(%p)", c);
@ -139,6 +141,21 @@ kore_connection_handle(struct connection *c)
}
}
if (SSL_get_verify_mode(c->ssl) & SSL_VERIFY_PEER) {
c->cert = SSL_get_peer_certificate(c->ssl);
if (c->cert == NULL) {
kore_log(LOG_NOTICE,
"no client certificate presented?");
return (KORE_RESULT_ERROR);
}
if (X509_GET_CN(c->cert, cn, sizeof(cn)) == -1) {
kore_log(LOG_NOTICE,
"no CN found in client certificate");
return (KORE_RESULT_ERROR);
}
}
r = SSL_get_verify_result(c->ssl);
if (r != X509_V_OK) {
kore_debug("SSL_get_verify_result(): %d, %s",
@ -219,6 +236,9 @@ kore_connection_remove(struct connection *c)
SSL_free(c->ssl);
}
if (c->cert != NULL)
X509_free(c->cert);
close(c->fd);
if (c->hdlr_extra != NULL)