forked from mirrors/kore
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:
parent
75c4bb0754
commit
1375190936
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue