aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pow/POW-0.7/POW.c117
-rw-r--r--rpkid/rpki/https.py20
-rw-r--r--rpkid/testbed.py29
3 files changed, 104 insertions, 62 deletions
diff --git a/pow/POW-0.7/POW.c b/pow/POW-0.7/POW.c
index 0191d9a2..cea6f04f 100644
--- a/pow/POW-0.7/POW.c
+++ b/pow/POW-0.7/POW.c
@@ -281,6 +281,7 @@ typedef struct {
int ctxset;
SSL *ssl;
SSL_CTX *ctx;
+ STACK_OF(X509) *trusted_certs;
} ssl_object;
typedef struct {
@@ -707,30 +708,31 @@ X509_object_helper_get_name(X509_NAME *name, int format)
static STACK_OF(X509) *
x509_helper_sequence_to_stack(PyObject *x509_sequence)
{
- x509_object *tmpX509 = NULL;
+ x509_object *x509obj = NULL;
STACK_OF(X509) *x509_stack = NULL;
int size = 0, i = 0;
if (x509_sequence != Py_None && !PyTuple_Check(x509_sequence) && !PyList_Check(x509_sequence))
- lose_type_error("inapropriate type");
+ lose_type_error("Inapropriate type");
if ((x509_stack = sk_X509_new_null()) == NULL)
- lose("could not create new x509 stack");
+ lose("Couldn't create new X509 stack");
if (x509_sequence != Py_None) {
size = PySequence_Size(x509_sequence);
for (i = 0; i < size; i++) {
- if ((tmpX509 = (x509_object*)PySequence_GetItem(x509_sequence, i)) == NULL)
+ if ((x509obj = (x509_object*) PySequence_GetItem(x509_sequence, i)) == NULL)
goto error;
- if (!X_X509_Check(tmpX509))
- lose_type_error("inapropriate type");
+ if (!X_X509_Check(x509obj))
+ lose_type_error("Inapropriate type");
+
+ if (!sk_X509_push(x509_stack, x509obj->x509))
+ lose("Couldn't add X509 object to stack");
- if (!sk_X509_push(x509_stack, tmpX509->x509))
- lose("could not add x509 to stack");
- Py_DECREF(tmpX509);
- tmpX509 = NULL;
+ Py_DECREF(x509obj);
+ x509obj = NULL;
}
}
@@ -738,10 +740,10 @@ x509_helper_sequence_to_stack(PyObject *x509_sequence)
error:
- if(x509_stack)
+ if (x509_stack)
sk_X509_free(x509_stack);
- Py_XDECREF(tmpX509);
+ Py_XDECREF(x509obj);
return NULL;
}
@@ -3959,22 +3961,36 @@ ssl_object_add_certificate(ssl_object *self, PyObject *args)
}
static PyObject *
-ssl_object_trust_certificate(ssl_object *self, PyObject *args)
+ssl_object_add_trust(ssl_object *self, PyObject *args)
{
x509_object *x509 = NULL;
+ X509 *x = NULL;
if (!PyArg_ParseTuple(args, "O!", &x509type, &x509))
goto error;
if (self->ctxset)
- lose("cannot be called after setFd()");
+ lose("Cannot be called after setFd()");
+
+ if (self->trusted_certs == NULL &&
+ (self->trusted_certs = sk_X509_new_null()) == NULL)
+ lose("Couldn't allocate trusted certificate stack");
+
+ if ((x = X509_dup(x509->x509)) == NULL)
+ lose("Couldn't duplicate X509 object");
- X509_STORE_add_cert(SSL_CTX_get_cert_store(self->ctx), x509->x509);
+ if (!sk_X509_push(self->trusted_certs, x))
+ lose("Couldn't push cert onto trusted certificate stack");
+
+ x = NULL;
return Py_BuildValue("");
error:
+ if (x)
+ X509_free(x);
+
return NULL;
}
@@ -4702,41 +4718,54 @@ ssl_object_get_cipher(ssl_object *self, PyObject *args)
return NULL;
}
-static int stub_callback(int ok, X509_STORE_CTX *ctx)
+static int ssl_object_verify_callback(X509_STORE_CTX *ctx, void *arg)
{
+ ssl_object *self = arg;
+ int ok;
+
+ if (self->trusted_certs)
+ X509_STORE_CTX_trusted_stack(ctx, self->trusted_certs);
+
+ ok = X509_verify_cert(ctx);
#if 0
+
+#warning
+#warning Nasty raw stderr debugging code enabled in ssl_object_verify_callback()
+#warning Do not use this code in production
+#warning
+
#include <stdio.h>
- if (!ok)
+
+ if (self->trusted_certs) {
+ int i;
+ fprintf(stderr, "Trusted cert stack\n");
+ for (i = 0; i < sk_X509_num(self->trusted_certs); i++) {
+ X509 *x = sk_X509_value(self->trusted_certs, i);
+ fprintf(stderr, "[%d] ", i);
+ if (x)
+ X509_print_fp(stderr, x);
+ else
+ fprintf(stderr, "<NULL>!\n");
+ }
+ } else {
+ fprintf(stderr, "No trusted cert stack\n");
+ }
+
+ if (!ok) {
fprintf(stderr,
- "Callback depth %d error %d cert %p issuer %p crl %p: %s\n",
+ "\nX509_verify_cert() error: callback depth %d error %d cert %p issuer %p crl %p: %s\n",
ctx->error_depth,
ctx->error,
ctx->current_cert,
ctx->current_issuer,
ctx->current_crl,
X509_verify_cert_error_string(ctx->error));
-#endif
-
-#if 1
- /*
- * Ok, this is wrong, but...what I really want to do is bypass
- * OpenSSL's baroque filesystem-based lookup system entirely, using
- * X509_STORE_CTX_trusted_stack(), but that call operates on an
- * X509_STORE_CTX, not an X509_STORE, which makes it, well, not
- * impossible to drop in here, but requires a lot of busywork using
- * SSL_CTX_set_cert_verify_callback() to replace the entire built-in
- * validator. I'll get to that eventually, but I have more urgent
- * tasks today, so for now I'm kludging around an error that happens
- * not to be dangerous given the way my application calls this code.
- */
-
-#warning
-#warning Clean up X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN override
-#warning
-
- if (!ok && ctx->error_depth > 0 && ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)
- ok = 1;
+ if (ctx->current_cert)
+ X509_print_fp(stderr, ctx->current_cert);
+ if (ctx->current_issuer)
+ X509_print_fp(stderr, ctx->current_issuer);
+ }
#endif
return ok;
@@ -4781,7 +4810,7 @@ ssl_object_set_verify_mode(ssl_object *self, PyObject *args)
if (self->ctxset)
lose("cannot be called after setfd()");
- SSL_CTX_set_verify(self->ctx, mode, stub_callback);
+ SSL_CTX_set_verify(self->ctx, mode, NULL);
return Py_BuildValue("");
@@ -4793,7 +4822,7 @@ ssl_object_set_verify_mode(ssl_object *self, PyObject *args)
static struct PyMethodDef ssl_object_methods[] = {
{"useCertificate", (PyCFunction)ssl_object_use_certificate, METH_VARARGS, NULL},
{"addCertificate", (PyCFunction)ssl_object_add_certificate, METH_VARARGS, NULL},
- {"trustCertificate", (PyCFunction)ssl_object_trust_certificate,METH_VARARGS, NULL},
+ {"addTrust", (PyCFunction)ssl_object_add_trust, METH_VARARGS, NULL},
{"useKey", (PyCFunction)ssl_object_use_key, METH_VARARGS, NULL},
{"checkKey", (PyCFunction)ssl_object_check_key, METH_VARARGS, NULL},
{"setFd", (PyCFunction)ssl_object_set_fd, METH_VARARGS, NULL},
@@ -4826,6 +4855,7 @@ newssl_object(int type)
self->ctxset = 0;
self->ssl = NULL;
+ self->trusted_certs = NULL;
switch (type) {
case SSLV2_SERVER_METHOD: method = SSLv2_server_method(); break;
@@ -4843,12 +4873,13 @@ newssl_object(int type)
default:
lose("unknown ctx method");
-
}
if ((self->ctx = SSL_CTX_new(method)) == NULL)
lose("unable to create new ctx");
+ SSL_CTX_set_cert_verify_callback(self->ctx, ssl_object_verify_callback, self);
+
return self;
error:
@@ -4868,6 +4899,8 @@ ssl_object_dealloc(ssl_object *self)
{
SSL_free(self->ssl);
SSL_CTX_free(self->ctx);
+ if (self->trusted_certs)
+ sk_X509_pop_free(self->trusted_certs, X509_free);
PyObject_Del(self);
}
diff --git a/rpkid/rpki/https.py b/rpkid/rpki/https.py
index 60f50909..9bf79474 100644
--- a/rpkid/rpki/https.py
+++ b/rpkid/rpki/https.py
@@ -353,6 +353,10 @@ class http_stream(asynchat.async_chat):
except POW.WantWriteError:
self.retry_write = self.close
+ def log_cert(self, tag, x):
+ if debug_tls_certs:
+ self.log("HTTPS %s cert %r issuer %s [%s] subject %s [%s]" % (tag, x, x.getIssuer(), x.hAKI(), x.getSubject(), x.hSKI()))
+
class http_server(http_stream):
parse_type = http_request
@@ -366,8 +370,7 @@ class http_server(http_stream):
self.log("cert %r key %r ta %r dynamic_ta %r" % (cert, key, ta, dynamic_ta))
self.tls = POW.Ssl(POW.TLSV1_SERVER_METHOD)
- if debug_tls_certs:
- self.log("HTTPS server cert issuer %s [%s] subject %s [%s]" % (cert.getIssuer(), cert.hAKI(), cert.getSubject(), cert.hSKI()))
+ self.log_cert("server", cert)
self.tls.useCertificate(cert.get_POW())
self.tls.useKey(key.get_POW())
ta = set(dynamic_ta() if dynamic_ta else ta)
@@ -375,9 +378,8 @@ class http_server(http_stream):
if not ta:
raise RuntimeError, "No trust anchor(s) specified, this is unlikely to work"
for x in ta:
- if debug_tls_certs:
- self.log("HTTPS trusted cert issuer %s [%s] subject %s [%s]" % (x.getIssuer(), x.hAKI(), x.getSubject(), x.hSKI()))
- self.tls.trustCertificate(x.get_POW())
+ self.log_cert("trusted", x)
+ self.tls.addTrust(x.get_POW())
self.tls.setVerifyMode(POW.SSL_VERIFY_PEER | POW.SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
self.tls.setFd(self.fileno())
@@ -514,16 +516,14 @@ class http_client(http_stream):
self.set_state("idle")
self.tls = POW.Ssl(POW.TLSV1_CLIENT_METHOD)
- if debug_tls_certs:
- self.log("HTTPS client cert issuer %s [%s] subject %s [%s]" % (self.cert.getIssuer(), self.cert.hAKI(), self.cert.getSubject(), self.cert.hSKI()))
+ self.log_cert("client", self.cert)
self.tls.useCertificate(self.cert.get_POW())
self.tls.useKey(self.key.get_POW())
if not self.ta:
raise RuntimeError, "No trust anchor(s) specified, this is unlikely to work"
for x in self.ta:
- if debug_tls_certs:
- self.log("HTTPS trusted cert issuer %s [%s] subject %s [%s]" % (x.getIssuer(), x.hAKI(), x.getSubject(), x.hSKI()))
- self.tls.trustCertificate(x.get_POW())
+ self.log_cert("trusted", x)
+ self.tls.addTrust(x.get_POW())
self.tls.setVerifyMode(POW.SSL_VERIFY_PEER | POW.SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
self.tls.setFd(self.fileno())
diff --git a/rpkid/testbed.py b/rpkid/testbed.py
index 2451a5a7..728ac607 100644
--- a/rpkid/testbed.py
+++ b/rpkid/testbed.py
@@ -809,7 +809,9 @@ class allocation(object):
else:
subprocess.check_call(cmd)
- return rpki.x509.X509(Auto_file = certfile)
+ x = rpki.x509.X509(Auto_file = certfile)
+ rpki.log.debug("Cross certified (%s) issuer %s [%s] subject %s [%s]" % (certfile, x.getIssuer(), x.hAKI(), x.getSubject(), x.hSKI()))
+ return x
def create_rpki_objects(self, cb):
"""
@@ -977,18 +979,25 @@ class allocation(object):
if s.is_root():
rootd_cert = s.cross_certify(rootd_name + "-TA")
- pdus.append(rpki.left_right.parent_elt.make_pdu(action = "create", tag = str(i), self_id = s.self_id, bsc_id = s.bsc_id,
- repository_id = s.repository_id, sia_base = s.sia_base,
- bpki_cms_cert = rootd_cert, bpki_https_cert = rootd_cert, sender_name = s.name, recipient_name = "Walrus",
- peer_contact_uri = "https://localhost:%s/" % rootd_port))
+ pdus.append(rpki.left_right.parent_elt.make_pdu(
+ action = "create", tag = str(i), self_id = s.self_id, bsc_id = s.bsc_id, repository_id = s.repository_id,
+ sia_base = s.sia_base,
+ bpki_cms_cert = rootd_cert,
+ bpki_https_cert = rootd_cert,
+ sender_name = s.name,
+ recipient_name = "Walrus",
+ peer_contact_uri = "https://localhost:%s/" % rootd_port))
else:
parent_cms_cert = s.cross_certify(s.parent.name + "-SELF")
parent_https_cert = s.cross_certify(s.parent.name + "-TA")
- pdus.append(rpki.left_right.parent_elt.make_pdu(action = "create", tag = str(i), self_id = s.self_id, bsc_id = s.bsc_id,
- repository_id = s.repository_id, sia_base = s.sia_base,
- bpki_cms_cert = parent_cms_cert, bpki_https_cert = parent_https_cert,
- sender_name = s.name, recipient_name = s.parent.name,
- peer_contact_uri = "https://localhost:%s/up-down/%s" % (s.parent.get_rpki_port(), s.child_id)))
+ pdus.append(rpki.left_right.parent_elt.make_pdu(
+ action = "create", tag = str(i), self_id = s.self_id, bsc_id = s.bsc_id, repository_id = s.repository_id,
+ sia_base = s.sia_base,
+ bpki_cms_cert = parent_cms_cert,
+ bpki_https_cert = parent_https_cert,
+ sender_name = s.name,
+ recipient_name = s.parent.name,
+ peer_contact_uri = "https://localhost:%s/up-down/%s" % (s.parent.get_rpki_port(), s.child_id)))
assert pdus, "%s has no parents, something is whacked" % self.name