diff options
author | Rob Austein <sra@hactrn.net> | 2015-12-07 00:14:06 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2015-12-07 00:14:06 +0000 |
commit | 5230fd448e5c86c1bf285d5d16574af17fa65897 (patch) | |
tree | dd2cf7cd545cbda7f72547c8b659cc7647474192 | |
parent | e72ed120fd831aebd8443b3075651d3e48e593b0 (diff) |
Move validation callback to Python.
svn path=/branches/tk705/; revision=6210
-rw-r--r-- | ext/POW.c | 91 | ||||
-rwxr-xr-x | rp/rcynic/rcynicng | 25 | ||||
-rw-r--r-- | rpki/POW/__init__.py | 3 |
3 files changed, 34 insertions, 85 deletions
@@ -1177,82 +1177,6 @@ _record_validation_status(PyObject *status, const char *code) return result == 0; } -/* - * Validation callback code for use with x509_verify_cert(). - * - * There's no direct way to handle exceptions here, so we're depending - * on x509_store_object_verify() calling PyErr_Occurred() to check - * (which it has to do anyway to handle exceptions generated by Python - * callback handlers. - */ - -#warning Probably most of this callback handler should become Python code - -static int -validation_status_x509_verify_cert_cb(int ok, X509_STORE_CTX *ctx, PyObject *status) -{ - switch (ctx->error) { - case X509_V_OK: - return ok; - - case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: - /* - * Informational events, not really errors. ctx->check_issued() - * is called in many places where failure to find an issuer is not - * a failure for the calling function. Just leave these alone. - */ -#warning Could be done in Python - return ok; - - case X509_V_ERR_CRL_HAS_EXPIRED: - /* - * This isn't really an error, because CRLs don't really - * "expire". - */ - -#warning Could be done in Python - return 1; - - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - /* - * This is another error that's only an error in the strange world - * of OpenSSL, but a more serious one. By default, OpenSSL - * expects all trust anchors to be self-signed. This is not a - * PKIX requirement, it's just an OpenSSL thing, but one violates - * it at one's peril, because the only way to convince OpenSSL to - * allow a non-self-signed trust anchor is to intercept this - * "error" in the verify callback handler. - * - * So this program supports non-self-signed trust anchors, but be - * warned that enabling this feature may cause this program's - * output not to work with other OpenSSL-based applications. - */ -#warning Could be done in Python -#if 0 - if (allow_non_self_signed_trust_anchor) - ok = 1; -#endif - record_validation_status(status, TRUST_ANCHOR_NOT_SELF_SIGNED); - return ok; - - /* - * Handle all other OpenSSL verify errors by stuffing an integer - * into the status set. - */ -#warning Could be done in Python - default: - if (status != Py_None) { - PyObject *value = PyInt_FromLong(ctx->error); - PySet_Add(status, value); - Py_XDECREF(value); - } - return ok; - } - - error: - return ok; -} - /* @@ -1425,7 +1349,7 @@ static int check_x509(X509 *x, ok = sk_ACCESS_DESCRIPTION_num(aia) > 0; for (i = 0; ok && i < sk_ACCESS_DESCRIPTION_num(aia); i++) { ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(aia, i); - ok = (a != NULL && a->location->type == GEN_URI || + ok = (a != NULL && a->location->type == GEN_URI && OBJ_obj2nid(a->method) == NID_ad_ca_issuers); } if (!ok) @@ -4958,13 +4882,6 @@ x509_store_ctx_object_verify_cb(int ok, X509_STORE_CTX *ctx) if (self == NULL) return ok; - /* - * This is where we'd extract flags (allow_*, etc) to pass to the callback handler. - */ - - if (self->status != NULL && self->status != Py_None) - ok = validation_status_x509_verify_cert_cb(ok, ctx, self->status); - if (!PyObject_HasAttrString((PyObject *) self, method_name)) return ok; @@ -7834,6 +7751,9 @@ manifest_object_verify(manifest_object *self, PyObject *args, PyObject *kwds) lose_openssl_error("Couldn't decode manifest"); } + if (status != Py_None && !check_cms(self->cms.cms, status)) + goto error; + if (status != Py_None && !check_manifest(self->cms.cms, self->manifest, status)) goto error; @@ -8515,6 +8435,9 @@ roa_object_verify(roa_object *self, PyObject *args, PyObject *kwds) lose_openssl_error("Couldn't decode ROA"); } + if (status != Py_None && !check_cms(self->cms.cms, status)) + goto error; + if (status != Py_None && !check_roa(self->cms.cms, self->roa, status)) goto error; diff --git a/rp/rcynic/rcynicng b/rp/rcynic/rcynicng index b06154cb..fed75ab2 100755 --- a/rp/rcynic/rcynicng +++ b/rp/rcynic/rcynicng @@ -157,6 +157,28 @@ def final_install(): shutil.rmtree(path) +class X509StoreCTX(rpki.POW.X509StoreCTX): + + @classmethod + def subclass(cls, **kwargs): + return type(cls.__name__, (cls,), kwargs) + + status = None + + def verify_callback(self, ok): + err = self.getError() + if err in (codes.X509_V_OK.code, codes.X509_V_ERR_SUBJECT_ISSUER_MISMATCH.code): + return ok + elif err == codes.X509_V_ERR_CRL_HAS_EXPIRED.code: + return True + elif err == codes.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT.code: + self.status.add(codes.TRUST_ANCHOR_NOT_SELF_SIGNED) + return ok + else: + self.status.add(codes.find(err)) + return ok + + class X509(rpki.POW.X509): def __repr__(self): @@ -254,7 +276,8 @@ class X509(rpki.POW.X509): if not is_ta and self.count_uris(self.crldp) == 0: status.add(codes.MALFORMED_CRLDP_EXTENSION) try: - self.verify(trusted = [self] if trusted is None else trusted, crl = crl, status = status) + self.verify(trusted = [self] if trusted is None else trusted, crl = crl, status = status, + context_class = X509StoreCTX.subclass(status = status)) except rpki.POW.ValidationError as e: logger.debug("%r rejected: %s", self, e) status.add(codes.OBJECT_REJECTED) diff --git a/rpki/POW/__init__.py b/rpki/POW/__init__.py index 0b961e81..e88fae80 100644 --- a/rpki/POW/__init__.py +++ b/rpki/POW/__init__.py @@ -79,6 +79,9 @@ class StatusCodeDB(object): status.remove(s) status.add(self._map[s]) + def find(self, code): + return self._map[code] + validation_status = StatusCodeDB( bad = dict( |