aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rpkid/ext/POW.c408
1 files changed, 397 insertions, 11 deletions
diff --git a/rpkid/ext/POW.c b/rpkid/ext/POW.c
index 9e40aeb6..1d7cb73c 100644
--- a/rpkid/ext/POW.c
+++ b/rpkid/ext/POW.c
@@ -108,6 +108,8 @@
#include <time.h>
#include <string.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
/*
* Maximum size of a raw IP (v4 or v6) address, in bytes.
@@ -153,12 +155,13 @@
#define DER_FORMAT 2
/* Object check functions */
-#define X_X509_Check(op) ((op)->ob_type == &x509type)
-#define X_X509_store_Check(op) ((op)->ob_type == &x509_storetype)
-#define X_X509_crl_Check(op) ((op)->ob_type == &x509_crltype)
-#define X_asymmetric_Check(op) ((op)->ob_type == &asymmetrictype)
-#define X_digest_Check(op) ((op)->ob_type == &digesttype)
-#define X_cms_Check(op) ((op)->ob_type == &cmstype)
+#define POW_X509_Check(op) PyObject_TypeCheck(op, &x509type)
+#define POW_X509_Store_Check(op) PyObject_TypeCheck(op, &x509_storetype)
+#define POW_X509_CRL_Check(op) PyObject_TypeCheck(op, &x509_crltype)
+#define POW_Asymmetric_Check(op) PyObject_TypeCheck(op, &asymmetrictype)
+#define POW_Digest_Check(op) PyObject_TypeCheck(op, &digesttype)
+#define POW_CMS_Check(op) PyObject_TypeCheck(op, &cmstype)
+#define POW_IPAddress_Check(op) PyObject_TypeCheck(op, &ipaddresstype)
static char pow_module__doc__ [] =
"Python interface to RFC-3779-enabled OpenSSL. This code is intended\n"
@@ -189,10 +192,21 @@ static PyTypeObject
x509_crltype,
asymmetrictype,
digesttype,
- cmstype;
+ cmstype,
+ ipaddresstype;
+
/*========== Pre-definitions ==========*/
/*========== C structs ==========*/
+
+typedef struct {
+ PyObject_HEAD
+ unsigned char address[16];
+ unsigned char version;
+ unsigned char length;
+ unsigned short af;
+} ipaddress_object;
+
typedef struct {
PyObject_HEAD
X509 *x509;
@@ -550,7 +564,7 @@ x509_helper_sequence_to_stack(PyObject *x509_sequence)
if ((x509obj = (x509_object*) PySequence_GetItem(x509_sequence, i)) == NULL)
goto error;
- if (!X_X509_Check(x509obj))
+ if (!POW_X509_Check(x509obj))
lose_type_error("Inapropriate type");
if (!sk_X509_push(x509_stack, x509obj->x509))
@@ -688,7 +702,7 @@ Python_Long_to_ASN1_INTEGER(PyObject *py_long)
memset(buf, 0, sizeof(buf));
if (_PyLong_AsByteArray((PyLongObject *) py_long, buf, sizeof(buf), 0, 0) < 0)
- lose_type_error("Couldn't extract ASID value");
+ goto error;
while (b < buf + sizeof(buf) - 1 && *b == 0)
b++;
@@ -712,9 +726,380 @@ Python_Long_to_ASN1_INTEGER(PyObject *py_long)
return NULL;
}
+/*========== helper functions ==========*/
+/*========== IPAddress code ==========*/
-/*========== helper functions ==========*/
+static PyObject *
+ipaddress_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = {"initializer", "version", NULL};
+ ipaddress_object *self = NULL;
+ PyObject *init = NULL;
+ PyObject *pylong = NULL;
+ int version = 0;
+ const char *s = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &init, &version) ||
+ (self = (ipaddress_object *) type->tp_alloc(type, 0)) == NULL)
+ goto error;
+
+ if (POW_IPAddress_Check(init)) {
+ ipaddress_object *src = (ipaddress_object *) init;
+
+ memcpy(self->address, src->address, sizeof(self->address));
+ self->version = src->version;
+ self->length = src->length;
+ self->af = src->af;
+
+ return (PyObject *) self;
+ }
+
+ if ((s = PyString_AsString(init)) == NULL)
+ PyErr_Clear();
+ else if (version == 0)
+ version = strchr(s, ':') ? 6 : 4;
+
+ switch (version) {
+ case 4: self->length = 4; self->af = AF_INET; break;
+ case 6: self->length = 16; self->af = AF_INET6; break;
+ default: lose("Unknown IP version number");
+ }
+ self->version = version;
+
+ if (s != NULL) {
+ if (inet_pton(self->af, s, self->address) <= 0)
+ lose("Couldn't parse IP address");
+ return (PyObject *) self;
+ }
+
+ if ((pylong = PyNumber_Long(init)) != NULL) {
+ if (_PyLong_AsByteArray((PyLongObject *) pylong, self->address, self->length, 0, 0) < 0)
+ goto error;
+ Py_XDECREF(pylong);
+ return (PyObject *) self;
+ }
+
+ lose_type_error("Couldn't convert initializer to IPAddress");
+
+ error:
+ Py_XDECREF(self);
+ Py_XDECREF(pylong);
+ return NULL;
+}
+
+static PyObject *
+ipaddress_object_str(ipaddress_object *self)
+{
+ char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1];
+
+ if (!inet_ntop(self->af, self->address, addrstr, sizeof(addrstr)))
+ lose("Couldn't convert IP address");
+
+ return PyString_FromString(addrstr);
+
+ error:
+ return NULL;
+}
+
+static PyObject *
+ipaddress_object_repr(ipaddress_object *self)
+{
+ char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1];
+
+ if (!inet_ntop(self->af, self->address, addrstr, sizeof(addrstr)))
+ lose("Couldn't convert IP address");
+
+ return PyString_FromFormat("<%s object %s at %p>",
+ self->ob_type->tp_name, addrstr, self);
+
+ error:
+ return NULL;
+}
+
+static int
+ipaddress_object_compare(PyObject *arg1, PyObject *arg2)
+{
+ PyObject *obj1 = PyNumber_Long(arg1);
+ PyObject *obj2 = PyNumber_Long(arg2);
+ int cmp = -1;
+
+ if (obj1 != NULL && obj2 != NULL)
+ cmp = PyObject_Compare(obj1, obj2);
+
+ Py_XDECREF(obj1);
+ Py_XDECREF(obj2);
+ return cmp;
+}
+
+static PyObject *
+ipaddress_object_richcompare(PyObject *arg1, PyObject *arg2, int op)
+{
+ PyObject *obj1 = PyNumber_Long(arg1);
+ PyObject *obj2 = PyNumber_Long(arg2);
+ PyObject *result = NULL;
+
+ if (obj1 != NULL && obj2 != NULL)
+ result = PyObject_RichCompare(obj1, obj2, op);
+
+ Py_XDECREF(obj1);
+ Py_XDECREF(obj2);
+ return result;
+}
+
+static long
+ipaddress_object_hash(ipaddress_object *self)
+{
+ unsigned long h = 0;
+ int i;
+
+ for (i = 0; i < self->length; i++)
+ h ^= self->address[i] << ((i & 3) << 3);
+
+ return (long) h == -1 ? 0 : (long) h;
+}
+
+static PyObject *
+ipaddress_object_get_bits(ipaddress_object *self, void *closure)
+{
+ return PyInt_FromLong(self->length * 8);
+}
+
+static PyObject *
+ipaddress_object_number_binary_helper(binaryfunc function, PyObject *arg1, PyObject *arg2)
+{
+ ipaddress_object *addr = NULL;
+ ipaddress_object *addr1 = NULL;
+ ipaddress_object *addr2 = NULL;
+ ipaddress_object *result = NULL;
+ PyObject *obj1 = NULL;
+ PyObject *obj2 = NULL;
+ PyObject *obj3 = NULL;
+ PyObject *obj4 = NULL;
+
+ if (POW_IPAddress_Check(arg1))
+ addr1 = (ipaddress_object *) arg1;
+
+ if (POW_IPAddress_Check(arg2))
+ addr2 = (ipaddress_object *) arg2;
+
+ if ((addr1 == NULL && addr2 == NULL) ||
+ (addr1 != NULL && addr2 != NULL && addr1->version != addr2->version) ||
+ (obj1 = PyNumber_Long(arg1)) == NULL ||
+ (obj2 = PyNumber_Long(arg2)) == NULL) {
+ result = (ipaddress_object *) Py_NotImplemented;
+ goto error;
+ }
+
+ if ((obj3 = function(obj1, obj2)) == NULL)
+ goto error;
+
+ if ((obj4 = PyNumber_Long(obj3)) == NULL)
+ lose("Couldn't convert result");
+
+ addr = addr1 != NULL ? addr1 : addr2;
+
+ if ((result = (ipaddress_object *) addr->ob_type->tp_alloc(addr->ob_type, 0)) == NULL)
+ goto error;
+
+ result->version = addr->version;
+ result->length = addr->length;
+ result->af = addr->af;
+
+ if (_PyLong_AsByteArray((PyLongObject *) obj4, result->address, result->length, 0, 0) < 0) {
+ Py_XDECREF(result);
+ result = NULL;
+ }
+
+ error: /* Fall through */
+ Py_XDECREF(obj1);
+ Py_XDECREF(obj2);
+ Py_XDECREF(obj3);
+ Py_XDECREF(obj4);
+
+ return (PyObject *) result;
+}
+
+static PyObject *
+ipaddress_object_number_long(PyObject *arg)
+{
+ ipaddress_object *addr = (ipaddress_object *) arg;
+
+ if (!POW_IPAddress_Check(arg))
+ return Py_NotImplemented;
+
+ return _PyLong_FromByteArray(addr->address, addr->length, 0, 0);
+}
+
+static PyObject *
+ipaddress_object_number_int(PyObject *arg)
+{
+ return ipaddress_object_number_long(arg);
+}
+
+static PyObject *
+ipaddress_object_number_add(PyObject *arg1, PyObject *arg2)
+{
+ return ipaddress_object_number_binary_helper(PyNumber_Add, arg1, arg2);
+}
+
+static PyObject *
+ipaddress_object_number_subtract(PyObject *arg1, PyObject *arg2)
+{
+ return ipaddress_object_number_binary_helper(PyNumber_Subtract, arg1, arg2);
+}
+
+static PyObject *
+ipaddress_object_number_lshift(PyObject *arg1, PyObject *arg2)
+{
+ return ipaddress_object_number_binary_helper(PyNumber_Lshift, arg1, arg2);
+}
+
+static PyObject *
+ipaddress_object_number_rshift(PyObject *arg1, PyObject *arg2)
+{
+ return ipaddress_object_number_binary_helper(PyNumber_Rshift, arg1, arg2);
+}
+
+static PyObject *
+ipaddress_object_number_and(PyObject *arg1, PyObject *arg2)
+{
+ return ipaddress_object_number_binary_helper(PyNumber_And, arg1, arg2);
+}
+
+static PyObject *
+ipaddress_object_number_xor(PyObject *arg1, PyObject *arg2)
+{
+ return ipaddress_object_number_binary_helper(PyNumber_Xor, arg1, arg2);
+}
+
+static PyObject *
+ipaddress_object_number_or(PyObject *arg1, PyObject *arg2)
+{
+ return ipaddress_object_number_binary_helper(PyNumber_Or, arg1, arg2);
+}
+
+static int
+ipaddress_object_number_nonzero(ipaddress_object *self)
+{
+ int i;
+
+ for (i = 0; i < self->length; i++)
+ if (self->address[i] != 0)
+ return 1;
+ return 0;
+}
+
+static PyObject *
+ipaddress_object_number_invert(ipaddress_object *self)
+{
+ ipaddress_object *result = NULL;
+ int i;
+
+ if ((result = (ipaddress_object *) self->ob_type->tp_alloc(self->ob_type, 0)) == NULL)
+ goto error;
+
+ result->version = self->version;
+ result->length = self->length;
+ result->af = self->af;
+
+ for (i = 0; i < self->length; i++)
+ result->address[i] = ~self->address[i];
+
+ error: /* Fall through */
+ return (PyObject *) result;
+}
+
+static PyGetSetDef ipaddress_getsetters[] = {
+ {"bits", (getter) ipaddress_object_get_bits},
+ {NULL}
+};
+
+static PyNumberMethods ipaddress_NumberMethods = {
+ ipaddress_object_number_add, /* nb_add */
+ ipaddress_object_number_subtract, /* nb_subtract */
+ 0, /* nb_multiply */
+ 0, /* nb_divide */
+ 0, /* nb_remainder */
+ 0, /* nb_divmod */
+ 0, /* nb_power */
+ 0, /* nb_negative */
+ 0, /* nb_positive */
+ 0, /* nb_absolute */
+ (inquiry) ipaddress_object_number_nonzero, /* nb_nonzero */
+ (unaryfunc) ipaddress_object_number_invert, /* nb_invert */
+ ipaddress_object_number_lshift, /* nb_lshift */
+ ipaddress_object_number_rshift, /* nb_rshift */
+ ipaddress_object_number_and, /* nb_and */
+ ipaddress_object_number_xor, /* nb_xor */
+ ipaddress_object_number_or, /* nb_or */
+ 0, /* nb_coerce */
+ ipaddress_object_number_int, /* nb_int */
+ ipaddress_object_number_long, /* nb_long */
+ 0, /* nb_float */
+ 0, /* nb_oct */
+ 0, /* nb_hex */
+ 0, /* nb_inplace_add */
+ 0, /* nb_inplace_subtract */
+ 0, /* nb_inplace_multiply */
+ 0, /* nb_inplace_divide */
+ 0, /* nb_inplace_remainder */
+ 0, /* nb_inplace_power */
+ 0, /* nb_inplace_lshift */
+ 0, /* nb_inplace_rshift */
+ 0, /* nb_inplace_and */
+ 0, /* nb_inplace_xor */
+ 0, /* nb_inplace_or */
+ 0, /* nb_floor_divide */
+ 0, /* nb_true_divide */
+ 0, /* nb_inplace_floor_divide */
+ 0, /* nb_inplace_true_divide */
+ 0, /* nb_index */
+};
+
+static PyTypeObject ipaddresstype = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "_POW.IPAddress", /* tp_name */
+ sizeof(ipaddress_object), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ ipaddress_object_compare, /* tp_compare */
+ (reprfunc) ipaddress_object_repr, /* tp_repr */
+ &ipaddress_NumberMethods, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc) ipaddress_object_hash, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc) ipaddress_object_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ ipaddress_object_richcompare, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ ipaddress_getsetters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ ipaddress_object_new, /* tp_new */
+};
+
+/*========== IPAddress code ==========*/
/*========== X509 code ==========*/
@@ -3672,7 +4057,7 @@ cms_object_sign(cms_object *self, PyObject *args)
if ((crlobj = (x509_crl_object *) PySequence_GetItem(crl_sequence, i)) == NULL)
goto error;
- if (!X_X509_crl_Check(crlobj))
+ if (!POW_X509_CRL_Check(crlobj))
lose_type_error("Inappropriate type");
if (!crlobj->crl)
@@ -4384,6 +4769,7 @@ init_POW(void)
Define_Class(asymmetrictype);
Define_Class(digesttype);
Define_Class(cmstype);
+ Define_Class(ipaddresstype);
#undef Define_Class