diff options
Diffstat (limited to 'SWIG/_lib.i')
-rw-r--r-- | SWIG/_lib.i | 360 |
1 files changed, 289 insertions, 71 deletions
diff --git a/SWIG/_lib.i b/SWIG/_lib.i index 42dc180..c84b800 100644 --- a/SWIG/_lib.i +++ b/SWIG/_lib.i @@ -1,19 +1,85 @@ /* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. */ -/* $Id: _lib.i 695 2009-07-24 06:37:01Z heikki $ */ +/* $Id$ */ %{ +#include <openssl/bn.h> #include <openssl/dh.h> #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/rsa.h> #include <openssl/ssl.h> #include <openssl/x509.h> +#include <openssl/x509_vfy.h> #include <ceval.h> +%} + +/* OpenSSL 1.1 compatibility shim */ +%include _lib11_compat.i + +/* Python 3 compatibility shim */ +%include _py3k_compat.i + +%{ +/* OpenSSL 1.0.2 copmatbility shim */ +#if OPENSSL_VERSION_NUMBER < 0x10002000L +typedef void (*OPENSSL_sk_freefunc)(void *); +typedef void *(*OPENSSL_sk_copyfunc)(const void *); +typedef struct stack_st OPENSSL_STACK; + +# define MIN_NODES 4 +# define sk_deep_copy OPENSSL_sk_deep_copy + +void OPENSSL_sk_free(OPENSSL_STACK *st) +{ + if (st == NULL) + return; + OPENSSL_free(st->data); + OPENSSL_free(st); +} + +OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, + OPENSSL_sk_copyfunc copy_func, + OPENSSL_sk_freefunc free_func) +{ + OPENSSL_STACK *ret; + int i; + + if (sk->num < 0) + return NULL; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) + return NULL; + + /* direct structure assignment */ + *ret = *sk; + + ret->num_alloc = sk->num > MIN_NODES ? (size_t)sk->num : MIN_NODES; + ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc); + if (ret->data == NULL) { + OPENSSL_free(ret); + return NULL; + } + + for (i = 0; i < ret->num; ++i) { + if (sk->data[i] == NULL) + continue; + if ((ret->data[i] = copy_func(sk->data[i])) == NULL) { + while (--i >= 0) + if (ret->data[i] != NULL) + free_func((void *)ret->data[i]); + OPENSSL_sk_free(ret); + return NULL; + } + } + return ret; +} +#endif /* OpenSSL 1.0.2 copmatbility shim */ + /* Blob interface. Deprecated. */ Blob *blob_new(int len, const char *errmsg) { - + Blob *blob; if (!(blob=(Blob *)PyMem_Malloc(sizeof(Blob)))){ PyErr_SetString(PyExc_MemoryError, errmsg); @@ -47,9 +113,15 @@ void blob_free(Blob *blob) { /* Python helpers. */ %} +%ignore PyObject_CheckBuffer; +%ignore PyObject_GetBuffer; +%ignore PyBuffer_Release; %ignore m2_PyObject_AsReadBufferInt; +%ignore m2_PyObject_GetBufferInt; +%ignore m2_PyBuffer_Release; %ignore m2_PyString_AsStringAndSizeInt; %{ + static int m2_PyObject_AsReadBufferInt(PyObject *obj, const void **buffer, int *buffer_len) @@ -68,13 +140,63 @@ m2_PyObject_AsReadBufferInt(PyObject *obj, const void **buffer, return 0; } +static int m2_PyObject_GetBufferInt(PyObject *obj, Py_buffer *view, int flags) +{ + int ret; + + if (PyObject_CheckBuffer(obj)) + ret = PyObject_GetBuffer(obj, view, flags); + else { + const void *buf; + + ret = PyObject_AsReadBuffer(obj, &buf, &view->len); + if (ret == 0) + view->buf = (void *)buf; + } + if (ret) + return ret; + if (view->len > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "object too large"); + m2_PyBuffer_Release(obj, view); + return -1; + } + + return 0; +} + +static BIGNUM* +m2_PyObject_AsBIGNUM(PyObject* value, PyObject* _py_exc) +{ + BIGNUM* bn; + const void* vbuf; + int vlen = 0; + + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) + return NULL; + + if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { + PyErr_SetString(_py_exc, ERR_reason_error_string(ERR_get_error())); + return NULL; + } + + return bn; +} + +static void m2_PyBuffer_Release(PyObject *obj, Py_buffer *view) +{ + if (PyObject_CheckBuffer(obj)) + PyBuffer_Release(view); + /* else do nothing, view->buf comes from PyObject_AsReadBuffer */ +} + static int m2_PyString_AsStringAndSizeInt(PyObject *obj, char **s, int *len) { int ret; Py_ssize_t len2; - ret = PyString_AsStringAndSize(obj, s, &len2); + ret = PyBytes_AsStringAndSize(obj, s, &len2); + if (ret) return ret; if (len2 > INT_MAX) { @@ -85,8 +207,46 @@ m2_PyString_AsStringAndSizeInt(PyObject *obj, char **s, int *len) return 0; } +/* Works as PyFile_Name, but always returns a new object. */ +PyObject *m2_PyFile_Name(PyObject *pyfile) { + PyObject *out = NULL; +#if PY_MAJOR_VERSION >= 3 + out = PyObject_GetAttrString(pyfile, "name"); +#else + out = PyFile_Name(pyfile); + Py_XINCREF(out); +#endif + return out; +} + +/* Yes, __FUNCTION__ is a non-standard symbol, but it is supported by + * both gcc and MSVC. */ +#define m2_PyErr_Msg(type) m2_PyErr_Msg_Caller(type, (const char*) __FUNCTION__) + +static void m2_PyErr_Msg_Caller(PyObject *err_type, const char* caller) { + const char *err_reason; + const char *data; + int flags; + /* This max size of a (longer than ours) OpenSSL error string is hardcoded + * in OpenSSL's crypto/err/err_prn.c:ERR_print_errors_cb() */ + char err_msg[4096]; + unsigned long err_code = ERR_get_error_line_data(NULL, NULL, &data, &flags); + + if (err_code != 0) { + err_reason = ERR_reason_error_string(err_code); + if (data && (flags & ERR_TXT_STRING)) + snprintf(err_msg, sizeof(err_msg), "%s (%s)", err_reason, data); + else + snprintf(err_msg, sizeof(err_msg), "%s", err_reason); + + PyErr_SetString(err_type, err_msg); + } else { + PyErr_Format(err_type, "Unknown error in function %s.", caller); + } +} + -/* C callbacks invoked by OpenSSL; these in turn call back into +/* C callbacks invoked by OpenSSL; these in turn call back into Python. */ int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { @@ -100,6 +260,7 @@ int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { int cret; int new_style_callback = 0, warning_raised_exception=0; PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx); @@ -117,7 +278,7 @@ int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { PyCodeObject *code = (PyCodeObject *) PyFunction_GetCode(ssl_verify_cb_func); if (code && code->co_argcount == 2) { /* XXX Python internals */ new_style_callback = 1; - } + } } else { /* XXX There are lots of other callable types, but we will assume * XXX that any other type of callable uses the new style callback, @@ -125,30 +286,34 @@ int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { */ new_style_callback = 1; } - + if (new_style_callback) { - PyObject *x509mod = PyDict_GetItemString(PyImport_GetModuleDict(), "M2Crypto.X509"); + PyObject *x509mod; + + x509mod = PyDict_GetItemString(PyImport_GetModuleDict(), "M2Crypto.X509"); _klass = PyObject_GetAttrString(x509mod, "X509_Store_Context"); - + _x509_store_ctx_swigptr = SWIG_NewPointerObj((void *)ctx, SWIGTYPE_p_X509_STORE_CTX, 0); _x509_store_ctx_obj = Py_BuildValue("(Oi)", _x509_store_ctx_swigptr, 0); - _x509_store_ctx_inst = PyInstance_New(_klass, _x509_store_ctx_obj, NULL); + + _x509_store_ctx_inst = PyObject_CallObject(_klass, _x509_store_ctx_obj); + argv = Py_BuildValue("(iO)", ok, _x509_store_ctx_inst); } else { if (PyErr_Warn(PyExc_DeprecationWarning, "Old style callback, use cb_func(ok, store) instead")) { warning_raised_exception = 1; } - + x509 = X509_STORE_CTX_get_current_cert(ctx); errnum = X509_STORE_CTX_get_error(ctx); errdepth = X509_STORE_CTX_get_error_depth(ctx); - - ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx); + + ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); ssl_ctx = SSL_get_SSL_CTX(ssl); - + _x509 = SWIG_NewPointerObj((void *)x509, SWIGTYPE_p_X509, 0); _ssl_ctx = SWIG_NewPointerObj((void *)ssl_ctx, SWIGTYPE_p_SSL_CTX, 0); - argv = Py_BuildValue("(OOiii)", _ssl_ctx, _x509, errnum, errdepth, ok); + argv = Py_BuildValue("(OOiii)", _ssl_ctx, _x509, errnum, errdepth, ok); } if (!warning_raised_exception) { @@ -161,9 +326,10 @@ int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { /* Got an exception in PyEval_CallObject(), let's fail verification * to be safe. */ - cret = 0; + cret = 0; } else { - cret = (int)PyInt_AsLong(ret); + /* FIXME This is possibly problematic if ret > MAXINT */ + cret = (int)PyLong_AsLong(ret); } Py_XDECREF(ret); Py_XDECREF(argv); @@ -182,15 +348,59 @@ int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { return cret; } +int x509_store_verify_callback(int ok, X509_STORE_CTX *ctx) { + PyGILState_STATE gilstate; + PyObject *argv, *ret; + PyObject *_x509_store_ctx_swigptr=0, *_x509_store_ctx_obj=0, *_x509_store_ctx_inst=0, *_klass=0; + int cret; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ + PyObject *x509mod; + + + gilstate = PyGILState_Ensure(); + + /* Below, handle only what is called 'new style callback' in ssl_verify_callback(). + TODO: does 'old style callback' exist any more? */ + x509mod = PyDict_GetItemString(PyImport_GetModuleDict(), "M2Crypto.X509"); + _klass = PyObject_GetAttrString(x509mod, "X509_Store_Context"); + _x509_store_ctx_swigptr = SWIG_NewPointerObj((void *)ctx, SWIGTYPE_p_X509_STORE_CTX, 0); + _x509_store_ctx_obj = Py_BuildValue("(Oi)", _x509_store_ctx_swigptr, 0); + + _x509_store_ctx_inst = PyObject_CallObject(_klass, _x509_store_ctx_obj); + + argv = Py_BuildValue("(iO)", ok, _x509_store_ctx_inst); + + ret = PyEval_CallObject(x509_store_verify_cb_func, argv); + if (!ret) { + /* Got an exception in PyEval_CallObject(), let's fail verification + * to be safe. + */ + cret = 0; + } else { + cret = (int)PyInt_AsLong(ret); + } + + Py_XDECREF(ret); + Py_XDECREF(argv); + Py_XDECREF(_x509_store_ctx_inst); + Py_XDECREF(_x509_store_ctx_obj); + Py_XDECREF(_x509_store_ctx_swigptr); + Py_XDECREF(_klass); + + PyGILState_Release(gilstate); + return cret; +} + void ssl_info_callback(const SSL *s, int where, int ret) { PyObject *argv, *retval, *_SSL; PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ gilstate = PyGILState_Ensure(); _SSL = SWIG_NewPointerObj((void *)s, SWIGTYPE_p_SSL, 0); argv = Py_BuildValue("(iiO)", where, ret, _SSL); - + retval = PyEval_CallObject(ssl_info_cb_func, argv); Py_XDECREF(retval); @@ -204,6 +414,7 @@ DH *ssl_set_tmp_dh_callback(SSL *ssl, int is_export, int keylength) { PyObject *argv, *ret, *_ssl; DH *dh; PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ gilstate = PyGILState_Ensure(); @@ -227,6 +438,7 @@ RSA *ssl_set_tmp_rsa_callback(SSL *ssl, int is_export, int keylength) { PyObject *argv, *ret, *_ssl; RSA *rsa; PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ gilstate = PyGILState_Ensure(); @@ -246,17 +458,18 @@ RSA *ssl_set_tmp_rsa_callback(SSL *ssl, int is_export, int keylength) { return rsa; } -void gen_callback(int p, int n, void *arg) { +/* Universal callback for dh_generate_parameters, + * dsa_generate_parametersm, and rsa_generate_key */ +int bn_gencb_callback(int p, int n, BN_GENCB *gencb) { PyObject *argv, *ret, *cbfunc; - - PyGILState_STATE gilstate; - gilstate = PyGILState_Ensure(); - cbfunc = (PyObject *)arg; + + cbfunc = (PyObject *)BN_GENCB_get_arg(gencb); argv = Py_BuildValue("(ii)", p, n); ret = PyEval_CallObject(cbfunc, argv); + PyErr_Clear(); Py_DECREF(argv); Py_XDECREF(ret); - PyGILState_Release(gilstate); + return 1; } int passphrase_callback(char *buf, int num, int v, void *arg) { @@ -269,20 +482,25 @@ int passphrase_callback(char *buf, int num, int v, void *arg) { gilstate = PyGILState_Ensure(); cbfunc = (PyObject *)arg; argv = Py_BuildValue("(i)", v); + /* PyEval_CallObject sets exception, if needed. */ ret = PyEval_CallObject(cbfunc, argv); Py_DECREF(argv); if (ret == NULL) { PyGILState_Release(gilstate); return -1; } - if (!PyString_Check(ret)) { + + if (!PyBytes_Check(ret)) { + PyErr_SetString(PyExc_RuntimeError, + "Result of callback is not bytes()."); Py_DECREF(ret); PyGILState_Release(gilstate); return -1; } - if ((len = PyString_Size(ret)) > num) + if ((len = PyBytes_Size(ret)) > num) len = num; - str = PyString_AsString(ret); + str = PyBytes_AsString(ret); + for (i = 0; i < len; i++) buf[i] = str[i]; Py_DECREF(ret); @@ -292,34 +510,38 @@ int passphrase_callback(char *buf, int num, int v, void *arg) { %} %inline %{ + void lib_init() { +#if OPENSSL_VERSION_NUMBER < 0x10100000L SSLeay_add_all_algorithms(); ERR_load_ERR_strings(); +#endif } -/* Bignum routines that aren't not numerous enough to +/* Bignum routines that aren't not numerous enough to warrant a separate file. */ -PyObject *bn_to_mpi(BIGNUM *bn) { - int len; +PyObject *bn_to_mpi(const BIGNUM *bn) { + int len = 0; unsigned char *mpi; - PyObject *pyo; + PyObject *pyo; len = BN_bn2mpi(bn, NULL); if (!(mpi=(unsigned char *)PyMem_Malloc(len))) { - PyErr_SetString(PyExc_RuntimeError, - ERR_error_string(ERR_get_error(), NULL)); + m2_PyErr_Msg(PyExc_MemoryError); return NULL; } len=BN_bn2mpi(bn, mpi); - pyo=PyString_FromStringAndSize((const char *)mpi, len); + + pyo=PyBytes_FromStringAndSize((const char *)mpi, len); + PyMem_Free(mpi); return pyo; } -BIGNUM *mpi_to_bn(PyObject *value) { +const BIGNUM *mpi_to_bn(PyObject *value) { const void *vbuf; - int vlen; + int vlen = 0; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; @@ -328,9 +550,9 @@ BIGNUM *mpi_to_bn(PyObject *value) { } PyObject *bn_to_bin(BIGNUM *bn) { - int len; + int len = 0; unsigned char *bin; - PyObject *pyo; + PyObject *pyo; len = BN_num_bytes(bn); if (!(bin=(unsigned char *)PyMem_Malloc(len))) { @@ -338,14 +560,16 @@ PyObject *bn_to_bin(BIGNUM *bn) { return NULL; } BN_bn2bin(bn, bin); - pyo=PyString_FromStringAndSize((const char *)bin, len); + + pyo=PyBytes_FromStringAndSize((const char *)bin, len); + PyMem_Free(bin); return pyo; } -BIGNUM *bin_to_bn(PyObject *value) { +const BIGNUM *bin_to_bn(PyObject *value) { const void *vbuf; - int vlen; + int vlen = 0; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; @@ -355,25 +579,26 @@ BIGNUM *bin_to_bn(PyObject *value) { PyObject *bn_to_hex(BIGNUM *bn) { char *hex; - PyObject *pyo; - Py_ssize_t len; + PyObject *pyo; + Py_ssize_t len = 0; hex = BN_bn2hex(bn); if (!hex) { - PyErr_SetString(PyExc_RuntimeError, - ERR_error_string(ERR_get_error(), NULL)); + m2_PyErr_Msg(PyExc_RuntimeError); OPENSSL_free(hex); - return NULL; + return NULL; } len = strlen(hex); - pyo=PyString_FromStringAndSize(hex, len); + + pyo=PyBytes_FromStringAndSize(hex, len); + OPENSSL_free(hex); return pyo; } BIGNUM *hex_to_bn(PyObject *value) { const void *vbuf; - Py_ssize_t vlen; + Py_ssize_t vlen = 0; BIGNUM *bn; if (PyObject_AsReadBuffer(value, &vbuf, &vlen) == -1) @@ -384,8 +609,7 @@ BIGNUM *hex_to_bn(PyObject *value) { return NULL; } if (BN_hex2bn(&bn, (const char *)vbuf) <= 0) { - PyErr_SetString(PyExc_RuntimeError, - ERR_error_string(ERR_get_error(), NULL)); + m2_PyErr_Msg(PyExc_RuntimeError); BN_free(bn); return NULL; } @@ -394,7 +618,7 @@ BIGNUM *hex_to_bn(PyObject *value) { BIGNUM *dec_to_bn(PyObject *value) { const void *vbuf; - Py_ssize_t vlen; + Py_ssize_t vlen = 0; BIGNUM *bn; if (PyObject_AsReadBuffer(value, &vbuf, &vlen) == -1) @@ -405,8 +629,7 @@ BIGNUM *dec_to_bn(PyObject *value) { return NULL; } if ((BN_dec2bn(&bn, (const char *)vbuf) <= 0)) { - PyErr_SetString(PyExc_RuntimeError, - ERR_error_string(ERR_get_error(), NULL)); + m2_PyErr_Msg(PyExc_RuntimeError); BN_free(bn); return NULL; } @@ -418,23 +641,26 @@ BIGNUM *dec_to_bn(PyObject *value) { /* Various useful typemaps. */ %typemap(in) Blob * { - Py_ssize_t len; + Py_ssize_t len = 0; - if (!PyString_Check($input)) { + if (!PyBytes_Check($input)) { PyErr_SetString(PyExc_TypeError, "expected PyString"); return NULL; } - len=PyString_Size($input); + len=PyBytes_Size($input); + if (len > INT_MAX) { PyErr_SetString(PyExc_ValueError, "object too large"); - return -1; + return NULL; } $1=(Blob *)PyMem_Malloc(sizeof(Blob)); if (!$1) { PyErr_SetString(PyExc_MemoryError, "malloc Blob"); return NULL; } - $1->data=(unsigned char *)PyString_AsString($input); + + $1->data=(unsigned char *)PyBytes_AsString($input); + $1->len=len; } @@ -443,20 +669,14 @@ BIGNUM *dec_to_bn(PyObject *value) { Py_INCREF(Py_None); $result=Py_None; } else { - $result=PyString_FromStringAndSize((const char *)$1->data, $1->len); + + $result=PyBytes_FromStringAndSize((const char *)$1->data, $1->len); + PyMem_Free($1->data); PyMem_Free($1); } } -%typemap(in) FILE * { - if (!PyFile_Check($input)) { - PyErr_SetString(PyExc_TypeError, "expected PyFile"); - return NULL; - } - $1=PyFile_AsFile($input); -} - %typemap(in) PyObject *pyfunc { if (!PyCallable_Check($input)) { PyErr_SetString(PyExc_TypeError, "expected PyCallable"); @@ -466,7 +686,8 @@ BIGNUM *dec_to_bn(PyObject *value) { } %typemap(in) PyObject *pyblob { - if (!PyString_Check($input)) { + if (!PyBytes_Check($input)) { + PyErr_SetString(PyExc_TypeError, "expected PyString"); return NULL; } @@ -482,7 +703,7 @@ BIGNUM *dec_to_bn(PyObject *value) { } %typemap(out) int { - $result=PyInt_FromLong($1); + $result=PyLong_FromLong($1); if (PyErr_Occurred()) SWIG_fail; } @@ -493,9 +714,6 @@ BIGNUM *dec_to_bn(PyObject *value) { /* A bunch of "straight-thru" functions. */ -%rename(err_print_errors_fp) ERR_print_errors_fp; -%threadallow ERR_print_errors_fp; -extern void ERR_print_errors_fp(FILE *); %rename(err_print_errors) ERR_print_errors; %threadallow ERR_print_errors; extern void ERR_print_errors(BIO *); |