Ticket: https://fedorahosted.org/freeipa/ticket/4657
Patch attached. -- Martin Basti
From 15509e09b658e9b2460ce42081baa1bb77a4d1e8 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 24 Feb 2015 19:25:31 +0100 Subject: [PATCH] Fix memory leaks in ipap11helper Ticket: https://fedorahosted.org/freeipa/ticket/4657 --- ipapython/ipap11helper/p11helper.c | 295 ++++++++++++++++++++++++++----------- 1 file changed, 212 insertions(+), 83 deletions(-) diff --git a/ipapython/ipap11helper/p11helper.c b/ipapython/ipap11helper/p11helper.c index c638bbe849f1bbddc8004bd1c4cccc1128b1c9e7..e3a7a9399c12759c537d13a291dcdf6ec1a1efa4 100644 --- a/ipapython/ipap11helper/p11helper.c +++ b/ipapython/ipap11helper/p11helper.c @@ -197,9 +197,11 @@ unsigned char* unicode_to_char_array(PyObject *unicode, Py_ssize_t *l) { /* Copy string first, then DECREF * https://docs.python.org/2/c-api/string.html#c.PyString_AS_STRING */ - result = (unsigned char *) malloc((size_t) *l); + result = (unsigned char *) PyMem_Malloc((size_t) *l); if (result == NULL){ - PyErr_SetString(ipap11helperError, "Memory allocation error"); + Py_DECREF(utf8_str); + PyErr_NoMemory(); + return NULL; } else { memcpy(result, bytes, *l); } @@ -650,7 +652,9 @@ P11_Helper_generate_master_key(P11_Helper* self, PyObject *args, PyObject *kwds) PyObject *label_unicode = NULL; Py_ssize_t label_length = 0; + CK_BYTE *label = NULL; int r; + int error = 0; static char *kwlist[] = { "subject", "id", "key_length", "cka_copyable", "cka_decrypt", "cka_derive", "cka_encrypt", "cka_extractable", "cka_modifiable", "cka_private", "cka_sensitive", "cka_sign", @@ -672,26 +676,28 @@ P11_Helper_generate_master_key(P11_Helper* self, PyObject *args, PyObject *kwds) return NULL; } - CK_BYTE *label = (unsigned char*) unicode_to_char_array(label_unicode, + label = (unsigned char*) unicode_to_char_array(label_unicode, &label_length); CK_MECHANISM mechanism = { //TODO param? CKM_AES_KEY_GEN, NULL_PTR, 0 }; + if (label == NULL) return NULL; if ((key_length != 16) && (key_length != 24) && (key_length != 32)) { PyErr_SetString(ipap11helperError, "generate_master_key: key length allowed values are: 16, 24 and 32"); - return NULL; + error = 1; + goto final; } - //TODO free label if check failed - //TODO is label freed inside???? dont we use freed value later r = _id_exists(self, id, id_length, CKO_SECRET_KEY); if (r == 1) { PyErr_SetString(ipap11helperDuplicationError, "Master key with same ID already exists"); - return NULL; + error = 1; + goto final; } else if (r == -1) { - return NULL; + error = 1; + goto final; } /* Process keyword boolean arguments */ @@ -719,9 +725,15 @@ P11_Helper_generate_master_key(P11_Helper* self, PyObject *args, PyObject *kwds) rv = self->p11->C_GenerateKey(self->session, &mechanism, symKeyTemplate, sizeof(symKeyTemplate) / sizeof(CK_ATTRIBUTE), &master_key); - if (!check_return_value(rv, "generate master key")) + if (!check_return_value(rv, "generate master key")){ + error = 1; + goto final; + } +final: + if (label != NULL) PyMem_Free(label); + if (error){ return NULL; - + } return Py_BuildValue("k", master_key); } @@ -740,6 +752,8 @@ P11_Helper_generate_replica_key_pair(P11_Helper* self, PyObject *args, int id_length = 0; PyObject* label_unicode = NULL; Py_ssize_t label_length = 0; + CK_BYTE *label = NULL; + int error = 0; PyObj2Bool_mapping_t attrs_pub[] = { { NULL, &true }, //pub_en_cka_copyable { NULL, &false }, //pub_en_cka_derive @@ -806,30 +820,33 @@ P11_Helper_generate_replica_key_pair(P11_Helper* self, PyObject *args, return NULL; } - CK_BYTE *label = unicode_to_char_array(label_unicode, &label_length); + label = unicode_to_char_array(label_unicode, &label_length); + if (label == NULL) return NULL; CK_OBJECT_HANDLE public_key, private_key; CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 }; - //TODO free variables - r = _id_exists(self, id, id_length, CKO_PRIVATE_KEY); if (r == 1) { PyErr_SetString(ipap11helperDuplicationError, "Private key with same ID already exists"); - return NULL; + error = 1; + goto final; } else if (r == -1) { - return NULL; + error = 1; + goto final; } r = _id_exists(self, id, id_length, CKO_PUBLIC_KEY); if (r == 1) { PyErr_SetString(ipap11helperDuplicationError, "Public key with same ID already exists"); - return NULL; + error = 1; + goto final; } else if (r == -1) { - return NULL; + error = 1; + goto final; } /* Process keyword boolean arguments */ @@ -878,9 +895,16 @@ P11_Helper_generate_replica_key_pair(P11_Helper* self, PyObject *args, privateKeyTemplate, sizeof(privateKeyTemplate) / sizeof(CK_ATTRIBUTE), &public_key, &private_key); - if (!check_return_value(rv, "generate key pair")) - return NULL; + if (!check_return_value(rv, "generate key pair")){ + error = 1; + goto final; + } +final: + if (label != NULL) PyMem_Free(label); + if (error) { + return NULL; + } return Py_BuildValue("(kk)", public_key, private_key); } @@ -891,7 +915,7 @@ static PyObject * P11_Helper_find_keys(P11_Helper* self, PyObject *args, PyObject *kwds) { CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED; CK_OBJECT_CLASS *class_ptr = &class; - CK_BYTE *id = NULL; //TODO free + CK_BYTE *id = NULL; CK_BBOOL *ckawrap = NULL; CK_BBOOL *ckaunwrap = NULL; int id_length = 0; @@ -902,12 +926,13 @@ P11_Helper_find_keys(P11_Helper* self, PyObject *args, PyObject *kwds) { CK_OBJECT_HANDLE *objects = NULL; unsigned int objects_len = 0; PyObject *result_list = NULL; - const char *uri_str = NULL; //TODO free? + const char *uri_str = NULL; P11KitUri *uri = NULL; - CK_BYTE *label = NULL; //TODO free + CK_BYTE *label = NULL; CK_ATTRIBUTE template_static[MAX_TEMPLATE_LEN]; CK_ATTRIBUTE_PTR template = template_static; CK_ULONG template_len = MAX_TEMPLATE_LEN; + int error = 0; static char *kwlist[] = { "objclass", "label", "id", "cka_wrap", "cka_unwrap", "uri", NULL }; @@ -946,25 +971,26 @@ P11_Helper_find_keys(P11_Helper* self, PyObject *args, PyObject *kwds) { _fill_template_from_parts(template, &template_len, id, id_length, label, label_length, class_ptr, ckawrap, ckaunwrap); else { - if (!_parse_uri(uri_str, &uri)) - return 0; + if (!_parse_uri(uri_str, &uri)) { + error = 1; + goto final; + } template = p11_kit_uri_get_attributes(uri, &template_len); /* Do not deallocate URI while you are using the template. * Template contains pointers to values inside URI! */ } - if (!_find_key(self, template, template_len, &objects, &objects_len)) - return NULL; - - if (uri != NULL) - p11_kit_uri_free(uri); + if (!_find_key(self, template, template_len, &objects, &objects_len)){ + error = 1; + goto final; + } result_list = PyList_New(objects_len); if (result_list == NULL) { PyErr_SetString(ipap11helperError, "Unable to create list with results"); - free(objects); - return NULL; + error = 1; + goto final; } for (int i = 0; i < objects_len; ++i) { @@ -972,13 +998,18 @@ P11_Helper_find_keys(P11_Helper* self, PyObject *args, PyObject *kwds) { == -1) { PyErr_SetString(ipap11helperError, "Unable to add to value to result list"); - free(objects); Py_DECREF(result_list); - return NULL; + error = 1; + goto final; } } - - free(objects); +final: + if (label != NULL) PyMem_Free(label); + if (objects != NULL) free(objects); + if (uri != NULL) p11_kit_uri_free(uri); + if (error){ + return NULL; + } return result_list; } @@ -1068,38 +1099,55 @@ P11_Helper_export_RSA_public_key(P11_Helper* self, CK_OBJECT_HANDLE object) { CK_BYTE_PTR exponent = NULL; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_KEY_TYPE key_type = CKK_RSA; + int error = 0; CK_ATTRIBUTE obj_template[] = { { CKA_MODULUS, NULL_PTR, 0 }, { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 }, { CKA_CLASS, &class, sizeof(class) }, { CKA_KEY_TYPE, &key_type, sizeof(key_type) } }; rv = self->p11->C_GetAttributeValue(self->session, object, obj_template, 4); - if (!check_return_value(rv, "get RSA public key values - prepare")) - return NULL; + if (!check_return_value(rv, "get RSA public key values - prepare")){ + error = 1; + goto final; + } /* Set proper size for attributes*/ - modulus = (CK_BYTE_PTR) malloc( + modulus = (CK_BYTE_PTR) PyMem_Malloc( obj_template[0].ulValueLen * sizeof(CK_BYTE)); + if (modulus == NULL){ + PyErr_NoMemory(); + error = 1; + goto final; + } obj_template[0].pValue = modulus; - exponent = (CK_BYTE_PTR) malloc( + exponent = (CK_BYTE_PTR) PyMem_Malloc( obj_template[1].ulValueLen * sizeof(CK_BYTE)); + if (exponent == NULL){ + PyErr_NoMemory(); + error = 1; + goto final; + } obj_template[1].pValue = exponent; rv = self->p11->C_GetAttributeValue(self->session, object, obj_template, 4); - if (!check_return_value(rv, "get RSA public key values")) - return NULL; + if (!check_return_value(rv, "get RSA public key values")){ + error = 1; + goto final; + } /* Check if the key is RSA public key */ if (class != CKO_PUBLIC_KEY) { PyErr_SetString(ipap11helperError, "export_RSA_public_key: required public key class"); - return NULL; + error = 1; + goto final; } if (key_type != CKK_RSA) { PyErr_SetString(ipap11helperError, "export_RSA_public_key: required RSA key type"); - return NULL; + error = 1; + goto final; } rsa = RSA_new(); @@ -1109,6 +1157,7 @@ P11_Helper_export_RSA_public_key(P11_Helper* self, CK_OBJECT_HANDLE object) { if (n == NULL) { PyErr_SetString(ipap11helperError, "export_RSA_public_key: internal error: unable to convert modulus"); + error = 1; goto final; } @@ -1117,6 +1166,7 @@ P11_Helper_export_RSA_public_key(P11_Helper* self, CK_OBJECT_HANDLE object) { if (e == NULL) { PyErr_SetString(ipap11helperError, "export_RSA_public_key: internal error: unable to convert exponent"); + error = 1; goto final; } @@ -1127,6 +1177,7 @@ P11_Helper_export_RSA_public_key(P11_Helper* self, CK_OBJECT_HANDLE object) { if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) { PyErr_SetString(ipap11helperError, "export_RSA_public_key: internal error: EVP_PKEY_set1_RSA failed"); + error = 1; goto final; } @@ -1146,6 +1197,11 @@ P11_Helper_export_RSA_public_key(P11_Helper* self, CK_OBJECT_HANDLE object) { EVP_PKEY_free(pkey); if (pp != NULL) free(pp); + if (modulus != NULL) PyMem_Free(modulus); + if (exponent != NULL) PyMem_Free(exponent); + if (error){ + return NULL; + } return ret; } @@ -1211,36 +1267,49 @@ P11_Helper_import_RSA_public_key(P11_Helper* self, CK_UTF8CHAR *label, int modulus_len = 0; CK_BYTE_PTR exponent = NULL; int exponent_len = 0; + int error = 0; if (pkey->type != EVP_PKEY_RSA) { PyErr_SetString(ipap11helperError, "Required RSA public key"); - return NULL; + error = 1; + goto final; } rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) { PyErr_SetString(ipap11helperError, "import_RSA_public_key: EVP_PKEY_get1_RSA error"); - return NULL; + error = 1; + goto final; } /* convert BIGNUM to binary array */ - modulus = (CK_BYTE_PTR) malloc(BN_num_bytes(rsa->n)); + modulus = (CK_BYTE_PTR) PyMem_Malloc(BN_num_bytes(rsa->n)); + if (modulus == NULL){ + PyErr_NoMemory(); + error = 1; + goto final; + } modulus_len = BN_bn2bin(rsa->n, (unsigned char *) modulus); if (modulus == NULL) { PyErr_SetString(ipap11helperError, "import_RSA_public_key: BN_bn2bin modulus error"); - //TODO free - return NULL; + error = 1; + goto final; } - exponent = (CK_BYTE_PTR) malloc(BN_num_bytes(rsa->e)); + exponent = (CK_BYTE_PTR) PyMem_Malloc(BN_num_bytes(rsa->e)); + if (exponent == NULL){ + PyErr_NoMemory(); + error = 1; + goto final; + } exponent_len = BN_bn2bin(rsa->e, (unsigned char *) exponent); if (exponent == NULL) { PyErr_SetString(ipap11helperError, "import_RSA_public_key: BN_bn2bin exponent error"); - //TODO free - return NULL; + error = 1; + goto final; } CK_ATTRIBUTE template[] = { @@ -1267,9 +1336,13 @@ P11_Helper_import_RSA_public_key(P11_Helper* self, CK_UTF8CHAR *label, if (!check_return_value(rv, "create public key object")) return NULL; - if (rsa != NULL) - RSA_free(rsa); - +final: + if (rsa != NULL) RSA_free(rsa); + if (modulus != NULL) PyMem_Free(modulus); + if (exponent != NULL) PyMem_Free(exponent); + if (error){ + return NULL; + } return Py_BuildValue("k", object); } @@ -1289,6 +1362,7 @@ P11_Helper_import_public_key(P11_Helper* self, PyObject *args, PyObject *kwds) { Py_ssize_t data_length = 0; Py_ssize_t label_length = 0; EVP_PKEY *pkey = NULL; + int error = 0; PyObj2Bool_mapping_t attrs_pub[] = { { NULL, &true }, //pub_en_cka_copyable { NULL, &false }, //pub_en_cka_derive @@ -1328,9 +1402,11 @@ P11_Helper_import_public_key(P11_Helper* self, PyObject *args, PyObject *kwds) { if (r == 1) { PyErr_SetString(ipap11helperDuplicationError, "Public key with same ID already exists"); - return NULL; + error = 1; + goto final; } else if (r == -1) { - return NULL; + error = 1; + goto final; } /* Process keyword boolean arguments */ @@ -1342,7 +1418,8 @@ P11_Helper_import_public_key(P11_Helper* self, PyObject *args, PyObject *kwds) { if (pkey == NULL) { PyErr_SetString(ipap11helperError, "import_public_key: d2i_PUBKEY error"); - return NULL; + error = 1; + goto final; } switch (pkey->type) { case EVP_PKEY_RSA: @@ -1358,19 +1435,24 @@ P11_Helper_import_public_key(P11_Helper* self, PyObject *args, PyObject *kwds) { attrs_pub[pub_en_cka_wrap].bool); break; case EVP_PKEY_DSA: - ret = NULL; + error = 1; PyErr_SetString(ipap11helperError, "DSA is not supported"); break; case EVP_PKEY_EC: - ret = NULL; + error = 1; PyErr_SetString(ipap11helperError, "EC is not supported"); break; default: - ret = NULL; + error = 1; PyErr_SetString(ipap11helperError, "Unsupported key type"); } +final: if (pkey != NULL) EVP_PKEY_free(pkey); + if (label != NULL) PyMem_Free(label); + if (error){ + return NULL; + } return ret; } @@ -1387,6 +1469,8 @@ P11_Helper_export_wrapped_key(P11_Helper* self, PyObject *args, PyObject *kwds) CK_ULONG wrapped_key_len = 0; CK_MECHANISM wrapping_mech = { CKM_RSA_PKCS, NULL, 0 }; /* currently we don't support parameter in mechanism */ + PyObject *result = NULL; + int error = 0; static char *kwlist[] = { "key", "wrapping_key", "wrapping_mech", NULL }; //TODO check long overflow @@ -1419,20 +1503,37 @@ P11_Helper_export_wrapped_key(P11_Helper* self, PyObject *args, PyObject *kwds) rv = self->p11->C_WrapKey(self->session, &wrapping_mech, object_wrapping_key, object_key, NULL, &wrapped_key_len); - if (!check_return_value(rv, "key wrapping: get buffer length")) - return 0; - wrapped_key = malloc(wrapped_key_len); + if (!check_return_value(rv, "key wrapping: get buffer length")){ + error = 1; + goto final; + } + wrapped_key = PyMem_Malloc(wrapped_key_len); + if (wrapped_key == NULL){ + PyErr_NoMemory(); + error = 1; + goto final; + } if (wrapped_key == NULL) { rv = CKR_HOST_MEMORY; - if (!check_return_value(rv, "key wrapping: buffer allocation")) - return 0; + if (!check_return_value(rv, "key wrapping: buffer allocation")){ + error = 1; + goto final; + } } rv = self->p11->C_WrapKey(self->session, &wrapping_mech, object_wrapping_key, object_key, wrapped_key, &wrapped_key_len); - if (!check_return_value(rv, "key wrapping: wrapping")) - return NULL; + if (!check_return_value(rv, "key wrapping: wrapping")){ + error = 1; + goto final; + } + result = Py_BuildValue("s#", wrapped_key, wrapped_key_len); - return Py_BuildValue("s#", wrapped_key, wrapped_key_len); +final: + if (wrapped_key != NULL) PyMem_Free(wrapped_key); + if (error){ + return NULL; + } + return result; } @@ -1457,6 +1558,7 @@ P11_Helper_import_wrapped_secret_key(P11_Helper* self, PyObject *args, CK_MECHANISM wrapping_mech = { CKM_RSA_PKCS, NULL, 0 }; CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; CK_KEY_TYPE key_type = CKK_RSA; + int error = 0; PyObj2Bool_mapping_t attrs[] = { { NULL, &true }, //sec_en_cka_copyable { NULL, &false }, //sec_en_cka_decrypt @@ -1519,15 +1621,17 @@ P11_Helper_import_wrapped_secret_key(P11_Helper* self, PyObject *args, } label = (unsigned char*) unicode_to_char_array(label_unicode, - &label_length); //TODO verify signed/unsigned + &label_length); r = _id_exists(self, id, id_length, key_class); if (r == 1) { PyErr_SetString(ipap11helperDuplicationError, "Secret key with same ID already exists"); - return NULL; + error = 1; + goto final; } else if (r == -1) { - return NULL; + error = 1; + goto final; } /* Process keyword boolean arguments */ @@ -1558,9 +1662,14 @@ P11_Helper_import_wrapped_secret_key(P11_Helper* self, PyObject *args, unwrapping_key_object, wrapped_key, wrapped_key_len, template, sizeof(template) / sizeof(CK_ATTRIBUTE), &unwrapped_key_object); if (!check_return_value(rv, "import_wrapped_key: key unwrapping")) { + error = 1; + goto final; + } +final: + if (label != NULL) PyMem_Free(label); + if (error) { return NULL; } - return Py_BuildValue("k", unwrapped_key_object); } @@ -1586,6 +1695,7 @@ P11_Helper_import_wrapped_private_key(P11_Helper* self, PyObject *args, CK_MECHANISM wrapping_mech = { CKM_RSA_PKCS, NULL, 0 }; CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; CK_KEY_TYPE key_type = CKK_RSA; + int error = 0; PyObj2Bool_mapping_t attrs_priv[] = { { NULL, &false }, //priv_en_cka_always_authenticate { NULL, &true }, //priv_en_cka_copyable @@ -1629,15 +1739,17 @@ P11_Helper_import_wrapped_private_key(P11_Helper* self, PyObject *args, } label = (unsigned char*) unicode_to_char_array(label_unicode, - &label_length); //TODO verify signed/unsigned + &label_length); r = _id_exists(self, id, id_length, CKO_SECRET_KEY); if (r == 1) { PyErr_SetString(ipap11helperDuplicationError, "Secret key with same ID already exists"); - return NULL; + error = 1; + goto final; } else if (r == -1) { - return NULL; + error = 1; + goto final; } /* Process keyword boolean arguments */ @@ -1668,9 +1780,14 @@ P11_Helper_import_wrapped_private_key(P11_Helper* self, PyObject *args, unwrapping_key_object, wrapped_key, wrapped_key_len, template, sizeof(template) / sizeof(CK_ATTRIBUTE), &unwrapped_key_object); if (!check_return_value(rv, "import_wrapped_key: key unwrapping")) { + error = 1; + goto final; + } +final: + if (label != NULL) PyMem_Free(label); + if (error){ return NULL; } - return PyLong_FromUnsignedLong(unwrapped_key_object); } @@ -1687,6 +1804,7 @@ P11_Helper_set_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) { CK_ATTRIBUTE attribute; CK_RV rv; Py_ssize_t len = 0; + CK_UTF8CHAR *label = NULL; static char *kwlist[] = { "key_object", "attr", "value", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "kkO|", kwlist, &object, &attr, @@ -1739,7 +1857,8 @@ P11_Helper_set_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) { ret = NULL; goto final; } - attribute.pValue = unicode_to_char_array(value, &len); + label = unicode_to_char_array(value, &len); + attribute.pValue = label; /* check for conversion error */ if (attribute.pValue == NULL) { ret = NULL; @@ -1769,6 +1888,7 @@ P11_Helper_set_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) { if (!check_return_value(rv, "set_attribute")) ret = NULL; final: + if (label != NULL) PyMem_Free(label); Py_XINCREF(ret); return ret; } @@ -1784,6 +1904,7 @@ P11_Helper_get_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) { unsigned long attr = 0; CK_ATTRIBUTE attribute; CK_RV rv; + int error = 0; static char *kwlist[] = { "key_object", "attr", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "kk|", kwlist, &object, @@ -1801,19 +1922,24 @@ P11_Helper_get_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) { if (rv == CKR_ATTRIBUTE_TYPE_INVALID || template[0].ulValueLen == (unsigned long) -1) { PyErr_SetString(ipap11helperNotFound, "attribute does not exist"); - ret = NULL; + error = 1; goto final; } if (!check_return_value(rv, "get_attribute init")) { - ret = NULL; + error = 1; + goto final; + } + value = PyMem_Malloc(template[0].ulValueLen); + if (value == NULL){ + PyErr_NoMemory(); + error = 1; goto final; } - value = malloc(template[0].ulValueLen); template[0].pValue = value; rv = self->p11->C_GetAttributeValue(self->session, object, template, 1); if (!check_return_value(rv, "get_attribute")) { - ret = NULL; + error = 1; goto final; } @@ -1857,13 +1983,16 @@ P11_Helper_get_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) { ret = Py_BuildValue("k", *(unsigned long *) value); break; default: - ret = NULL; + error = 1; PyErr_SetString(ipap11helperError, "Unknown attribute"); goto final; } final: if (value != NULL) - free(value); + PyMem_Free(value); + if (error){ + return NULL; + } return ret; } -- 2.1.0
_______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel