diff options
author | yan11.meng <yan11.meng@samsung.com> | 2020-02-26 12:47:07 +0900 |
---|---|---|
committer | yan11.meng <yan11.meng@samsung.com> | 2020-02-26 12:47:07 +0900 |
commit | 13ec6f74c73b377d6233de42cc942846e976541b (patch) | |
tree | 894efb8d5e53dd68dd463f7b222406439f4f494d /SWIG/_bio.i | |
parent | 5015799de7fb1dc08b584c0044d8393e4062ff34 (diff) | |
download | python-M2Crypto-13ec6f74c73b377d6233de42cc942846e976541b.tar.gz python-M2Crypto-13ec6f74c73b377d6233de42cc942846e976541b.tar.bz2 python-M2Crypto-13ec6f74c73b377d6233de42cc942846e976541b.zip |
Imported Upstream version 0.35.1
Change-Id: Id4a444b8c1d11fee1026b433a47ca5aabcf11622
Diffstat (limited to 'SWIG/_bio.i')
-rw-r--r-- | SWIG/_bio.i | 366 |
1 files changed, 342 insertions, 24 deletions
diff --git a/SWIG/_bio.i b/SWIG/_bio.i index 441ba06..e85a275 100644 --- a/SWIG/_bio.i +++ b/SWIG/_bio.i @@ -4,8 +4,9 @@ * Portions created by Open Source Applications Foundation (OSAF) are * Copyright (C) 2004-2005 OSAF. All Rights Reserved. * Author: Heikki Toivonen -*/ -/* $Id: _bio.i 695 2009-07-24 06:37:01Z heikki $ */ + * + * Copyright 2018 Daniel Wozniak. All Rights Reserved.*/ +/* $Id$ */ %{ #include <openssl/bio.h> @@ -31,15 +32,8 @@ extern BIO_METHOD *BIO_f_cipher(void); extern BIO *BIO_new(BIO_METHOD *); %rename(bio_new_socket) BIO_new_socket; extern BIO *BIO_new_socket(int, int); -%rename(bio_new_fd) BIO_new_fd; -extern BIO *BIO_new_fd(int, int); -%rename(bio_new_fp) BIO_new_fp; -extern BIO *BIO_new_fp(FILE *, int); -%rename(bio_new_file) BIO_new_file; -extern BIO *BIO_new_file(const char *, const char *); -%rename(bio_free) BIO_free; -%threadallow BIO_free; -extern int BIO_free(BIO *); +%rename(bio_new_fd) BIO_new_pyfd; +%rename(bio_new_pyfd) BIO_new_pyfd; %rename(bio_free_all) BIO_free_all; %threadallow BIO_free_all; extern void BIO_free_all(BIO *); @@ -51,6 +45,9 @@ extern BIO *BIO_push(BIO *, BIO *); %rename(bio_pop) BIO_pop; extern BIO *BIO_pop(BIO *); +%rename(bio_eof) BIO_eof; +extern int BIO_eof(BIO *); + %constant int bio_noclose = BIO_NOCLOSE; %constant int bio_close = BIO_CLOSE; %constant int BIO_FLAGS_READ = 0x01; @@ -60,12 +57,71 @@ extern BIO *BIO_pop(BIO *); %constant int BIO_FLAGS_SHOULD_RETRY = 0x08; %constant int BIO_FLAGS_MEM_RDONLY = 0x200; +%warnfilter(454) _bio_err; %inline %{ static PyObject *_bio_err; + +void pyfd_init(void); + void bio_init(PyObject *bio_err) { Py_INCREF(bio_err); _bio_err = bio_err; + pyfd_init(); +} + +int bio_free(BIO *bio) { + int ret; + + Py_BEGIN_ALLOW_THREADS + ret = BIO_free(bio); + Py_END_ALLOW_THREADS + if (ret == 0) { + m2_PyErr_Msg(_bio_err); + } + return ret; +} + +BIO * bio_new_file(const char *filename, const char *mode) { + BIO *ret; + + Py_BEGIN_ALLOW_THREADS + ret = BIO_new_file(filename, mode); + Py_END_ALLOW_THREADS + + if (ret == NULL) { + m2_PyErr_Msg(_bio_err); + } + + return ret; +} + +BIO *bio_new_pyfile(PyObject *pyfile, int bio_close) { + FILE *fp = NULL; + BIO *bio = NULL; + + fp = PyFile_AsFile(pyfile); + + bio = BIO_new_fp(fp, bio_close); + + /* returns NULL if error occurred */ + if (bio == NULL) { + /* Find out the name of the file so we can have good error + * message. */ + PyObject *pyname = m2_PyFile_Name(pyfile); + char *name = PyBytes_AsString(pyname); + + if (name == NULL) { + PyErr_Format(_bio_err, + "Opening of the new BIO on file failed!"); + } + else { + PyErr_Format(_bio_err, + "Opening of the new BIO on file %s failed!", name); + } + Py_DECREF(pyname); + } + return bio; } PyObject *bio_read(BIO *bio, int num) { @@ -83,13 +139,14 @@ PyObject *bio_read(BIO *bio, int num) { if (r < 0) { PyMem_Free(buf); if (ERR_peek_error()) { - PyErr_SetString(_bio_err, ERR_reason_error_string(ERR_get_error())); + m2_PyErr_Msg(_bio_err); return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } - blob = PyString_FromStringAndSize(buf, r); + + blob = PyBytes_FromStringAndSize(buf, r); + PyMem_Free(buf); return blob; } @@ -106,23 +163,24 @@ PyObject *bio_gets(BIO *bio, int num) { Py_BEGIN_ALLOW_THREADS r = BIO_gets(bio, buf, num); Py_END_ALLOW_THREADS - if (r < 0) { + if (r < 1) { PyMem_Free(buf); if (ERR_peek_error()) { - PyErr_SetString(_bio_err, ERR_reason_error_string(ERR_get_error())); + m2_PyErr_Msg(_bio_err); return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } - blob = PyString_FromStringAndSize(buf, r); + + blob = PyBytes_FromStringAndSize(buf, r); + PyMem_Free(buf); return blob; } int bio_write(BIO *bio, PyObject *from) { const void *fbuf; - int flen, ret; + int flen = 0, ret; if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) return -1; @@ -132,7 +190,8 @@ int bio_write(BIO *bio, PyObject *from) { Py_END_ALLOW_THREADS if (ret < 0) { if (ERR_peek_error()) { - PyErr_SetString(_bio_err, ERR_reason_error_string(ERR_get_error())); + m2_PyErr_Msg(_bio_err); + return -1; } } return ret; @@ -166,6 +225,10 @@ int bio_seek(BIO *bio, int offset) { return (int)BIO_seek(bio, offset); } +int bio_tell(BIO* bio) { + return BIO_tell(bio); +} + void bio_set_flags(BIO *bio, int flags) { BIO_set_flags(bio, flags); } @@ -174,6 +237,11 @@ int bio_get_flags(BIO *bio) { return BIO_get_flags(bio); } +/* + * sets the cipher of BIO @param b to c using key @param key and IV @iv. + * @param enc should be set to 1 for encryption and zero to decryption. + * + */ PyObject *bio_set_cipher(BIO *b, EVP_CIPHER *c, PyObject *key, PyObject *iv, int op) { const void *kbuf, *ibuf; Py_ssize_t klen, ilen; @@ -184,8 +252,7 @@ PyObject *bio_set_cipher(BIO *b, EVP_CIPHER *c, PyObject *key, PyObject *iv, int BIO_set_cipher(b, (const EVP_CIPHER *)c, (unsigned char *)kbuf, (unsigned char *)ibuf, op); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } int bio_set_mem_eof_return(BIO *b, int v) { @@ -197,6 +264,7 @@ int bio_get_fd(BIO *bio) { } %} +%warnfilter(454) methods_fdp; %threadallow bio_do_handshake; %inline %{ int bio_do_handshake(BIO *bio) { @@ -223,5 +291,255 @@ int bio_should_read(BIO* a) { int bio_should_write(BIO* a) { return BIO_should_write(a); } + +/* Macros for things not defined before 1.1.0 */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static BIO_METHOD * +BIO_meth_new( int type, const char *name ) +{ + BIO_METHOD *method = malloc( sizeof(BIO_METHOD) ); + memset( method, 0, sizeof(BIO_METHOD) ); + + method->type = type; + method->name = name; + + return method; +} + +static void +BIO_meth_free( BIO_METHOD *meth ) +{ + if ( meth == NULL ) { + return; + } + + free(meth); +} +#define BIO_meth_set_write(m, f) (m)->bwrite = (f) +#define BIO_meth_set_read(m, f) (m)->bread = (f) +#define BIO_meth_set_puts(m, f) (m)->bputs = (f) +#define BIO_meth_set_gets(m, f) (m)->bgets = (f) +#define BIO_meth_set_ctrl(m, f) (m)->ctrl = (f) +#define BIO_meth_set_create(m, f) (m)->create = (f) +#define BIO_meth_set_destroy(m, f) (m)->destroy = (f) +#define BIO_set_shutdown(b, x) (b)->shutdown = x +#define BIO_get_shutdown(b) (b)->shutdown +#define BIO_set_init(b, x) b->init = x +#define BIO_get_init(b) (b)->init +#define BIO_set_data(b, x) b->ptr = x +#define BIO_clear_flags(b, x) b->flags &= ~(x) +#define BIO_get_data(b) b->ptr +#endif + +/* implment custom BIO_s_pyfd */ + +#ifdef _WIN32 +# define clear_sys_error() SetLastError(0) +/* Linux doesn't use underscored calls yet */ +# define open(p, f, m) _open(p, f, m) +# define read(f, b, n) _read(f, b, n) +# define write(f, b, n) _write(f, b, n) +# define close(f) _close(f) +# define lseek(fd, o, w) _lseek(fd, o, w) +#else +# define clear_sys_error() errno=0 +#endif + +typedef struct pyfd_struct { + int fd; +} BIO_PYFD_CTX; + +/* Setting up methods_fdp */ +static BIO_METHOD *methods_fdp; + +static int pyfd_write(BIO *b, const char *in, int inl) { + int ret, fd; + + if (BIO_get_fd(b, &fd) == -1) { + PyErr_SetString(_bio_err, "BIO has not been initialized."); + return -1; + } + clear_sys_error(); + ret = write(fd, in, inl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_fd_should_retry(ret)) + BIO_set_retry_write(b); + } + return ret; +} + +static int pyfd_read(BIO *b, char *out, int outl) { + int ret = 0, fd; + + if (BIO_get_fd(b, &fd) == -1) { + PyErr_SetString(_bio_err, "BIO has not been initialized."); + return -1; + } + if (out != NULL) { + clear_sys_error(); + ret = read(fd, out, outl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_fd_should_retry(ret)) + BIO_set_retry_read(b); + } + } + return ret; +} + +static int pyfd_puts(BIO *bp, const char *str) { + int n, ret; + + n = strlen(str); + ret = pyfd_write(bp, str, n); + return ret; +} + +static int pyfd_gets(BIO *bp, char *buf, int size) { + int ret = 0; + char *ptr = buf; + char *end = buf + size - 1; + + /* See + https://github.com/openssl/openssl/pull/3442 + We were here just repeating a bug from OpenSSL + */ + while (ptr < end && pyfd_read(bp, ptr, 1) > 0) { + if (*ptr++ == '\n') + break; + } + + ptr[0] = '\0'; + + if (buf[0] != '\0') + ret = strlen(buf); + return ret; +} + +static int pyfd_new(BIO* b) { + BIO_PYFD_CTX* ctx; + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) + return 0; + + ctx->fd = -1; + + BIO_set_data(b, ctx); + BIO_set_shutdown(b, 0); + BIO_set_init(b, 1); + + return 1; + } + +static int pyfd_free(BIO* b) { + BIO_PYFD_CTX* ctx; + + if (b == 0) + return 0; + + ctx = BIO_get_data(b); + if (ctx == NULL) + return 0; + + if (BIO_get_shutdown(b) && BIO_get_init(b)) + close(ctx->fd); + + BIO_set_data(b, NULL); + BIO_set_shutdown(b, 0); + BIO_set_init(b, 0); + + OPENSSL_free(ctx); + + return 1; +} + +static long pyfd_ctrl(BIO *b, int cmd, long num, void *ptr) { + BIO_PYFD_CTX* ctx; + int *ip; + long ret = 1; + + ctx = BIO_get_data(b); + if (ctx == NULL) + return 0; + + switch (cmd) { + case BIO_CTRL_RESET: + num = 0; + case BIO_C_FILE_SEEK: + ret = (long)lseek(ctx->fd, num, 0); + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret = (long)lseek(ctx->fd, 0, 1); + break; + case BIO_C_SET_FD: + pyfd_free(b); + if (*((int *)ptr) > -1) { + if (!pyfd_new(b) || !(ctx = BIO_get_data(b))) + return 0; + ctx->fd = *((int *)ptr); + BIO_set_shutdown(b, (int)num); + BIO_set_init(b, 1); + } + break; + case BIO_C_GET_FD: + if (BIO_get_init(b)) { + ip = (int *)ptr; + if (ip != NULL) + *ip = ctx->fd; + ret = ctx->fd; + } else + ret = -1; + break; + case BIO_CTRL_GET_CLOSE: + ret = BIO_get_shutdown(b); + break; + case BIO_CTRL_SET_CLOSE: + BIO_set_shutdown(b, (int)num); + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +void pyfd_init(void) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + methods_fdp = BIO_meth_new( + BIO_get_new_index()|BIO_TYPE_DESCRIPTOR|BIO_TYPE_SOURCE_SINK, + "python file descriptor"); +#else + methods_fdp = BIO_meth_new( + 100 |BIO_TYPE_DESCRIPTOR|BIO_TYPE_SOURCE_SINK, + "python file descriptor"); +#endif + + BIO_meth_set_write(methods_fdp, pyfd_write); + BIO_meth_set_read(methods_fdp, pyfd_read); + BIO_meth_set_puts(methods_fdp, pyfd_puts); + BIO_meth_set_gets(methods_fdp, pyfd_gets); + BIO_meth_set_ctrl(methods_fdp, pyfd_ctrl); + BIO_meth_set_create(methods_fdp, pyfd_new); + BIO_meth_set_destroy(methods_fdp, pyfd_free); +} + +BIO* BIO_new_pyfd(int fd, int close_flag) { + BIO *ret; + + ret = BIO_new(methods_fdp); + BIO_set_fd(ret, fd, close_flag); + return ret; + } %} |