summaryrefslogtreecommitdiff
path: root/bcrypt/bcrypt_python.c
diff options
context:
space:
mode:
Diffstat (limited to 'bcrypt/bcrypt_python.c')
-rw-r--r--bcrypt/bcrypt_python.c93
1 files changed, 83 insertions, 10 deletions
diff --git a/bcrypt/bcrypt_python.c b/bcrypt/bcrypt_python.c
index 35147c0..a41352e 100644
--- a/bcrypt/bcrypt_python.c
+++ b/bcrypt/bcrypt_python.c
@@ -14,14 +14,20 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#endif
+
+#define PYBCRYPT_VERSION "0.4"
+
#if defined(_WIN32)
typedef unsigned __int8 u_int8_t;
typedef unsigned __int16 u_int16_t;
typedef unsigned __int32 u_int32_t;
#define bzero(s,n) memset(s, '\0', n)
-#define strdup _strdup
#endif
/* $Id$ */
@@ -40,7 +46,7 @@ bcrypt_encode_salt(PyObject *self, PyObject *args, PyObject *kw_args)
{
static char *keywords[] = { "csalt", "log_rounds", NULL };
u_int8_t *csalt = NULL;
- int csaltlen = -1;
+ Py_ssize_t csaltlen = -1;
long log_rounds = -1;
char ret[64];
@@ -56,7 +62,31 @@ bcrypt_encode_salt(PyObject *self, PyObject *args, PyObject *kw_args)
return NULL;
}
encode_salt(ret, csalt, csaltlen, log_rounds);
+#if PY_MAJOR_VERSION >= 3
+ return PyUnicode_FromString(ret);
+#else
return PyString_FromString(ret);
+#endif
+}
+
+/* Check that a string has no embedded '\0' characters and duplicate it. */
+static char *
+checkdup(const char *s, Py_ssize_t len)
+{
+ Py_ssize_t i;
+ char *ret;
+
+ if (len < 0)
+ return NULL;
+ for (i = 0; i < len; i++) {
+ if (s[i] == '\0')
+ return NULL;
+ }
+ if ((ret = malloc(len + 1)) == NULL)
+ return NULL;
+ memcpy(ret, s, len);
+ ret[len] = '\0';
+ return ret;
}
PyDoc_STRVAR(bcrypt_hashpw_doc,
@@ -70,15 +100,32 @@ bcrypt_hashpw(PyObject *self, PyObject *args, PyObject *kw_args)
static char *keywords[] = { "password", "salt", NULL };
char *password = NULL, *salt = NULL;
char hashed[128], *password_copy, *salt_copy;
+ Py_ssize_t password_len = -1, salt_len = -1;
int ret;
- if (!PyArg_ParseTupleAndKeywords(args, kw_args, "ss:hashpw", keywords,
- &password, &salt))
+ if (!PyArg_ParseTupleAndKeywords(args, kw_args, "s#s#:hashpw", keywords,
+ &password, &password_len, &salt, &salt_len))
return NULL;
- password_copy = strdup(password);
- salt_copy = strdup(salt);
-
+ if (password_len < 0 || password_len > 65535) {
+ PyErr_SetString(PyExc_ValueError,
+ "unsupported password length");
+ return NULL;
+ }
+ if (salt_len < 0 || salt_len > 65535) {
+ PyErr_SetString(PyExc_ValueError, "unsupported salt length");
+ return NULL;
+ }
+ if ((password_copy = checkdup(password, password_len)) == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "password must not contain nul characters");
+ return NULL;
+ }
+ if ((salt_copy = checkdup(salt, salt_len)) == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "salt must not contain nul characters");
+ return NULL;
+ }
Py_BEGIN_ALLOW_THREADS;
ret = pybc_bcrypt(password_copy, salt_copy, hashed, sizeof(hashed));
Py_END_ALLOW_THREADS;
@@ -91,8 +138,11 @@ bcrypt_hashpw(PyObject *self, PyObject *args, PyObject *kw_args)
PyErr_SetString(PyExc_ValueError, "Invalid salt");
return NULL;
}
-
+#if PY_MAJOR_VERSION >= 3
+ return PyUnicode_FromString(hashed);
+#else
return PyString_FromString(hashed);
+#endif
}
static PyMethodDef bcrypt_methods[] = {
@@ -105,12 +155,35 @@ static PyMethodDef bcrypt_methods[] = {
PyDoc_STRVAR(module_doc, "Internal module used by bcrypt.\n");
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef bcrypt_module = {
+ PyModuleDef_HEAD_INIT,
+ "bcrypt._bcrypt", /* m_name */
+ module_doc, /* m_doc */
+ -1, /* m_size */
+ bcrypt_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+PyMODINIT_FUNC
+PyInit__bcrypt(void)
+{
+ PyObject *m;
+
+ m = PyModule_Create(&bcrypt_module);
+ PyModule_AddStringConstant(m, "__version__", PYBCRYPT_VERSION);
+ return m;
+}
+#else
PyMODINIT_FUNC
init_bcrypt(void)
{
PyObject *m;
m = Py_InitModule3("bcrypt._bcrypt", bcrypt_methods, module_doc);
- PyModule_AddStringConstant(m, "__version__", "0.3");
+ PyModule_AddStringConstant(m, "__version__", PYBCRYPT_VERSION);
}
-
+#endif