diff options
author | Rob Austein <sra@hactrn.net> | 2012-09-12 04:53:19 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2012-09-12 04:53:19 +0000 |
commit | 5920d57f472709c34a96839aab748b924291812f (patch) | |
tree | 0c9ffc53eebbc38212788000a74896b42050fe2b | |
parent | 0984fac73f335a22b46e1b02fac03e99c428275a (diff) |
Checkpoint
svn path=/branches/tk274/; revision=4710
-rw-r--r-- | rpkid/ext/POW.c | 217 |
1 files changed, 163 insertions, 54 deletions
diff --git a/rpkid/ext/POW.c b/rpkid/ext/POW.c index 67bd5bae..fff82b7a 100644 --- a/rpkid/ext/POW.c +++ b/rpkid/ext/POW.c @@ -109,6 +109,16 @@ #include <time.h> #include <string.h> +/* + * Maximum size of a raw IP (v4 or v6) address, in bytes. + */ +#define RAW_IPADDR_BUFLEN 16 + +/* + * Maximum size of a raw autonomous system number, in bytes. + */ +#define RAW_ASNUMBER_BUFLEN 4 + /* PEM encoded data types */ #define RSA_PUBLIC_KEY 1 #define RSA_PRIVATE_KEY 2 @@ -663,6 +673,47 @@ BIO_to_PyString_helper(BIO *bio) #define Define_Method(__python_name__, __c_name__, __flags__) \ { #__python_name__, (PyCFunction) __c_name__, __flags__, __c_name__##__doc__ } +/* + * Convert a Python long to an ASN1_INTEGER. + * Do not read after eating. + */ +static ASN1_INTEGER * +Python_Long_to_ASN1_INTEGER(PyObject *py_long) +{ + ASN1_INTEGER *a = NULL; + unsigned char buf[RAW_ASNUMBER_BUFLEN]; + unsigned char *b = buf; + size_t len; + + 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"); + + while (b < buf + sizeof(buf) - 1 && *b == 0) + b++; + len = buf + sizeof(buf) - b; + + if ((a = ASN1_INTEGER_new()) == NULL || + (a->length < len + 1 && + (a->data = OPENSSL_realloc(a->data, len + 1)) == NULL)) + lose_no_memory(); + + a->type = V_ASN1_INTEGER; + a->length = len; + a->data[len] = 0; + + memcpy(a->data, b, len); + + return a; + + error: + ASN1_INTEGER_free(a); + return NULL; +} + + + /*========== helper functions ==========*/ /*========== X509 code ==========*/ @@ -1407,28 +1458,6 @@ x509_object_set_key_usage(x509_object *self, PyObject *args) return NULL; } -static int -addr_expand(unsigned char *addr, - const ASN1_BIT_STRING *bs, - const int length, - const unsigned char fill) -{ - if (bs->length < 0 || bs->length > length) - return 0; - if (bs->length > 0) { - memcpy(addr, bs->data, bs->length); - if ((bs->flags & 7) != 0) { - unsigned char mask = 0xFF >> (8 - (bs->flags & 7)); - if (fill == 0) - addr[bs->length - 1] &= ~mask; - else - addr[bs->length - 1] |= mask; - } - } - memset(addr + bs->length, fill, length - bs->length); - return 1; -} - static char x509_object_get_rfc3779__doc__[] = "This method returns the certificate's RFC 3779 resources. This is a\n" "three-element tuple: the first element is the ASN resources, the\n" @@ -1508,7 +1537,6 @@ x509_object_get_rfc3779(x509_object *self) } } - if ((addr = X509_get_ext_d2i(self->x509, NID_sbgp_ipAddrBlock, NULL, NULL)) != NULL) { for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); @@ -1517,16 +1545,9 @@ x509_object_get_rfc3779(x509_object *self) int addr_len = 0; switch (afi) { - case IANA_AFI_IPV4: - result_obj = &ipv4_result; - addr_len = 4; - break; - case IANA_AFI_IPV6: - result_obj = &ipv6_result; - addr_len = 16; - break; - default: - lose_type_error("Unknown AFI"); + case IANA_AFI_IPV4: result_obj = &ipv4_result; break; + case IANA_AFI_IPV6: result_obj = &ipv6_result; break; + default: lose_type_error("Unknown AFI"); } if (*result_obj != NULL) @@ -1536,41 +1557,29 @@ x509_object_get_rfc3779(x509_object *self) lose_type_error("Unsupported SAFI"); switch (f->ipAddressChoice->type) { + case IPAddressChoice_inherit: if ((*result_obj = PyString_FromString("inherit")) == NULL) goto error; continue; + case IPAddressChoice_addressesOrRanges: break; + default: lose_type_error("Unexpected IPAddressChoice type"); } - if ((*result_obj = - PyTuple_New(sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges))) == NULL) + if ((*result_obj = PyTuple_New(sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges))) == NULL) goto error; for (j = 0; j < sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges); j++) { - const IPAddressOrRange *aor = sk_IPAddressOrRange_value(f->ipAddressChoice->u.addressesOrRanges, j); - ASN1_BIT_STRING *b = NULL; - ASN1_BIT_STRING *e = NULL; - unsigned char b_buf[16], e_buf[16]; - - switch (aor->type) { - case IPAddressOrRange_addressPrefix: - b = e = aor->u.addressPrefix; - break; - case IPAddressOrRange_addressRange: - b = aor->u.addressRange->min; - e = aor->u.addressRange->max; - break; - default: - lose_type_error("Unexpected IPAddressOrRange type"); - } + IPAddressOrRange *aor = sk_IPAddressOrRange_value(f->ipAddressChoice->u.addressesOrRanges, + j); + unsigned char b_buf[RAW_IPADDR_BUFLEN], e_buf[RAW_IPADDR_BUFLEN]; - if (!addr_expand(b_buf, b, addr_len, 0x00) || - !addr_expand(e_buf, e, addr_len, 0xFF)) - lose_type_error("BIT STRINGs do not contain valid IP addresses"); + if ((addr_len = v3_addr_get_range(aor, afi, b_buf, e_buf, RAW_IPADDR_BUFLEN)) == 0) + lose_type_error("Couldn't unpack IP addresses from BIT STRINGs"); if ((range_b = _PyLong_FromByteArray(b_buf, addr_len, 0, 0)) == NULL || (range_e = _PyLong_FromByteArray(e_buf, addr_len, 0, 0)) == NULL || @@ -1601,6 +1610,105 @@ x509_object_get_rfc3779(x509_object *self) return result; } +static char x509_object_set_rfc3779__doc__[] = + "This method sets the certificate's RFC 3779 resources.\n" + "\n" + "[Add description here once argument format is stable]\n" + ; + +static PyObject * +x509_object_set_rfc3779(x509_object *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"asn", "ipv4", "ipv6", NULL}; + PyObject *asn_arg = Py_None; + PyObject *ipv4_arg = Py_None; + PyObject *ipv6_arg = Py_None; + PyObject *iterator = NULL; + PyObject *item = NULL; + PyObject *range_b = NULL; + PyObject *range_e = NULL; + ASIdentifiers *asid = NULL; + IPAddrBlocks *addr = NULL; + int i, j; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &asn_arg, &ipv4_arg, &ipv6_arg)) + goto error; + + if (asn_arg != Py_None) { + + if ((asid = ASIdentifiers_new()) == NULL) + lose_no_memory(); + + if (PyString_Check(asn_arg)) { + + if (strcmp(PyString_AsString(asn_arg), "inherit")) + lose_type_error("ASID must be sequence of range pairs, or \"inherit\""); + + if (!v3_asid_add_inherit(asid, V3_ASID_ASNUM)) + lose_no_memory(); + + } else { + + if ((iterator = PyObject_GetIter(asn_arg)) == NULL) + goto error; + + while ((item = PyIter_Next(iterator)) != NULL) { + ASN1_INTEGER *b = NULL; + ASN1_INTEGER *e = NULL; + + if (!PyArg_ParseTuple(item, "OO", &range_b, &range_e) || + !PyLong_Check(range_b) || + !PyLong_Check(range_e)) + lose_type_error("ASID must be sequence of range pairs, or \"inherit\""); + + if ((b = Python_Long_to_ASN1_INTEGER(range_b)) == NULL) + goto error; + + switch (PyObject_RichCompareBool(range_b, range_e, Py_EQ)) { + case 0: + if ((e = Python_Long_to_ASN1_INTEGER(range_e)) == NULL) { + ASN1_INTEGER_free(b); + goto error; + } + case 1: + break; + default: + ASN1_INTEGER_free(b); + lose_type_error("Couldn't compare range values"); + } + + if (!v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, b, e)) { + ASN1_INTEGER_free(b); + ASN1_INTEGER_free(e); + lose_openssl_error("Couldn't add range to ASID"); + } + + b = e = NULL; + Py_XDECREF(item); + item = NULL; + } + + if (!v3_asid_canonize(asid) || + !X509_add1_ext_i2d(self->x509, NID_sbgp_autonomousSysNum, + asid, 1, X509V3_ADD_REPLACE)) + lose_openssl_error("Couldn't add ASID extension to certificate"); + + Py_XDECREF(iterator); + iterator = NULL; + } + } + + if (ipv4_arg != Py_None || ipv6_arg != Py_None) { + } + + Py_RETURN_NONE; + + error: + Py_XDECREF(iterator); + Py_XDECREF(item); + return NULL; +} + static char x509_object_pprint__doc__[] = "This method returns a pretty-printed rendition of the certificate.\n" ; @@ -1651,6 +1759,7 @@ static struct PyMethodDef x509_object_methods[] = { Define_Method(getKeyUsage, x509_object_get_key_usage, METH_NOARGS), Define_Method(setKeyUsage, x509_object_set_key_usage, METH_VARARGS), Define_Method(getRFC3779, x509_object_get_rfc3779, METH_NOARGS), + Define_Method(setRFC3779, x509_object_set_rfc3779, METH_KEYWORDS), {NULL} }; |