1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* Copyright (c) 1999 Ng Pheng Siong. All rights reserved.
3  *
4  * Portions created by Open Source Applications Foundation (OSAF) are
5  * Copyright (C) 2004-2005 OSAF. All Rights Reserved.
6  * Author: Heikki Toivonen
7  *
8  * Copyright 2018 Daniel Wozniak. All Rights Reserved.*/
9 /* $Id$ */
10 
11 %{
12 #include <openssl/bio.h>
13 %}
14 
15 %apply Pointer NONNULL { BIO * };
16 %apply Pointer NONNULL { BIO_METHOD * };
17 
18 %rename(bio_s_bio) BIO_s_bio;
19 extern BIO_METHOD *BIO_s_bio(void);
20 %rename(bio_s_mem) BIO_s_mem;
21 extern BIO_METHOD *BIO_s_mem(void);
22 %rename(bio_s_socket) BIO_s_socket;
23 extern BIO_METHOD *BIO_s_socket(void);
24 %rename(bio_f_ssl) BIO_f_ssl;
25 extern BIO_METHOD *BIO_f_ssl(void);
26 %rename(bio_f_buffer) BIO_f_buffer;
27 extern BIO_METHOD *BIO_f_buffer(void);
28 %rename(bio_f_cipher) BIO_f_cipher;
29 extern BIO_METHOD *BIO_f_cipher(void);
30 
31 %rename(bio_new) BIO_new;
32 extern BIO *BIO_new(BIO_METHOD *);
33 %rename(bio_new_socket) BIO_new_socket;
34 extern BIO *BIO_new_socket(int, int);
35 %rename(bio_new_fd) BIO_new_pyfd;
36 %rename(bio_new_pyfd) BIO_new_pyfd;
37 %rename(bio_free_all) BIO_free_all;
38 %threadallow BIO_free_all;
39 extern void BIO_free_all(BIO *);
40 %rename(bio_dup_chain) BIO_dup_chain;
41 extern BIO *BIO_dup_chain(BIO *);
42 
43 %rename(bio_push) BIO_push;
44 extern BIO *BIO_push(BIO *, BIO *);
45 %rename(bio_pop) BIO_pop;
46 extern BIO *BIO_pop(BIO *);
47 
48 %rename(bio_eof) BIO_eof;
49 extern int BIO_eof(BIO *);
50 
51 %constant int bio_noclose             = BIO_NOCLOSE;
52 %constant int bio_close               = BIO_CLOSE;
53 %constant int BIO_FLAGS_READ          = 0x01;
54 %constant int BIO_FLAGS_WRITE         = 0x02;
55 %constant int BIO_FLAGS_IO_SPECIAL    = 0x04;
56 %constant int BIO_FLAGS_RWS = (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL);
57 %constant int BIO_FLAGS_SHOULD_RETRY  = 0x08;
58 %constant int BIO_FLAGS_MEM_RDONLY    = 0x200;
59 
60 %warnfilter(454) _bio_err;
61 %inline %{
62 static PyObject *_bio_err;
63 
64 
65 void pyfd_init(void);
66 
bio_init(PyObject * bio_err)67 void bio_init(PyObject *bio_err) {
68     Py_INCREF(bio_err);
69     _bio_err = bio_err;
70     pyfd_init();
71 }
72 
bio_free(BIO * bio)73 int bio_free(BIO *bio) {
74     int ret;
75 
76     Py_BEGIN_ALLOW_THREADS
77     ret = BIO_free(bio);
78     Py_END_ALLOW_THREADS
79     if (ret == 0) {
80         m2_PyErr_Msg(_bio_err);
81     }
82     return ret;
83 }
84 
bio_new_file(const char * filename,const char * mode)85 BIO * bio_new_file(const char *filename, const char *mode) {
86     BIO *ret;
87 
88     Py_BEGIN_ALLOW_THREADS
89     ret = BIO_new_file(filename, mode);
90     Py_END_ALLOW_THREADS
91 
92     if (ret == NULL) {
93         m2_PyErr_Msg(_bio_err);
94     }
95 
96     return ret;
97 }
98 
bio_new_pyfile(PyObject * pyfile,int bio_close)99 BIO *bio_new_pyfile(PyObject *pyfile, int bio_close) {
100     FILE *fp = NULL;
101     BIO *bio = NULL;
102 
103     fp = PyFile_AsFile(pyfile);
104 
105     bio = BIO_new_fp(fp, bio_close);
106 
107     /* returns NULL if error occurred */
108     if (bio == NULL) {
109         /* Find out the name of the file so we can have good error
110          * message. */
111         PyObject *pyname = m2_PyFile_Name(pyfile);
112         char *name = PyBytes_AsString(pyname);
113 
114         if (name == NULL) {
115             PyErr_Format(_bio_err,
116                          "Opening of the new BIO on file failed!");
117         }
118         else {
119             PyErr_Format(_bio_err,
120                          "Opening of the new BIO on file %s failed!", name);
121         }
122         Py_DECREF(pyname);
123     }
124     return bio;
125 }
126 
bio_read(BIO * bio,int num)127 PyObject *bio_read(BIO *bio, int num) {
128     PyObject *blob;
129     void *buf;
130     int r;
131 
132     if (!(buf = PyMem_Malloc(num))) {
133         PyErr_SetString(PyExc_MemoryError, "bio_read");
134         return NULL;
135     }
136     Py_BEGIN_ALLOW_THREADS
137     r = BIO_read(bio, buf, num);
138     Py_END_ALLOW_THREADS
139     if (r < 0) {
140         PyMem_Free(buf);
141         if (ERR_peek_error()) {
142             m2_PyErr_Msg(_bio_err);
143             return NULL;
144         }
145         Py_RETURN_NONE;
146     }
147 
148     blob = PyBytes_FromStringAndSize(buf, r);
149 
150     PyMem_Free(buf);
151     return blob;
152 }
153 
bio_gets(BIO * bio,int num)154 PyObject *bio_gets(BIO *bio, int num) {
155     PyObject *blob;
156     void *buf;
157     int r;
158 
159     if (!(buf = PyMem_Malloc(num))) {
160         PyErr_SetString(PyExc_MemoryError, "bio_gets");
161         return NULL;
162     }
163     Py_BEGIN_ALLOW_THREADS
164     r = BIO_gets(bio, buf, num);
165     Py_END_ALLOW_THREADS
166     if (r < 1) {
167         PyMem_Free(buf);
168         if (ERR_peek_error()) {
169             m2_PyErr_Msg(_bio_err);
170             return NULL;
171         }
172         Py_RETURN_NONE;
173     }
174 
175     blob = PyBytes_FromStringAndSize(buf, r);
176 
177     PyMem_Free(buf);
178     return blob;
179 }
180 
bio_write(BIO * bio,PyObject * from)181 int bio_write(BIO *bio, PyObject *from) {
182     const void *fbuf;
183     int flen = 0, ret;
184 
185     if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1)
186         return -1;
187 
188     Py_BEGIN_ALLOW_THREADS
189     ret = BIO_write(bio, fbuf, flen);
190     Py_END_ALLOW_THREADS
191     if (ret < 0) {
192         if (ERR_peek_error()) {
193             m2_PyErr_Msg(_bio_err);
194             return -1;
195         }
196     }
197     return ret;
198 }
199 
200 /* XXX Casting size_t to int. */
bio_ctrl_pending(BIO * bio)201 int bio_ctrl_pending(BIO *bio) {
202     return (int)BIO_ctrl_pending(bio);
203 }
204 
bio_ctrl_wpending(BIO * bio)205 int bio_ctrl_wpending(BIO *bio) {
206     return (int)BIO_ctrl_wpending(bio);
207 }
208 
bio_ctrl_get_write_guarantee(BIO * a)209 int bio_ctrl_get_write_guarantee(BIO *a) {
210     return BIO_ctrl_get_write_guarantee(a);
211 }
212 
bio_reset(BIO * bio)213 int bio_reset(BIO *bio) {
214     return (int)BIO_reset(bio);
215 }
216 %}
217 
218 %threadallow bio_flush;
219 %inline %{
bio_flush(BIO * bio)220 int bio_flush(BIO *bio) {
221     return (int)BIO_flush(bio);
222 }
223 
bio_seek(BIO * bio,int offset)224 int bio_seek(BIO *bio, int offset) {
225     return (int)BIO_seek(bio, offset);
226 }
227 
bio_tell(BIO * bio)228 int bio_tell(BIO* bio) {
229     return BIO_tell(bio);
230 }
231 
bio_set_flags(BIO * bio,int flags)232 void bio_set_flags(BIO *bio, int flags) {
233     BIO_set_flags(bio, flags);
234 }
235 
bio_get_flags(BIO * bio)236 int bio_get_flags(BIO *bio) {
237     return BIO_get_flags(bio);
238 }
239 
240 /*
241  * sets the cipher of BIO @param b to c using key @param key and IV @iv.
242  * @param enc should be set to 1 for encryption and zero to decryption.
243  *
244  */
bio_set_cipher(BIO * b,EVP_CIPHER * c,PyObject * key,PyObject * iv,int op)245 PyObject *bio_set_cipher(BIO *b, EVP_CIPHER *c, PyObject *key, PyObject *iv, int op) {
246     const void *kbuf, *ibuf;
247     Py_ssize_t klen, ilen;
248 
249     if ((m2_PyObject_AsReadBuffer(key, &kbuf, &klen) == -1)
250         || (m2_PyObject_AsReadBuffer(iv, &ibuf, &ilen) == -1))
251         return NULL;
252 
253     BIO_set_cipher(b, (const EVP_CIPHER *)c,
254         (unsigned char *)kbuf, (unsigned char *)ibuf, op);
255     Py_RETURN_NONE;
256 }
257 
bio_set_mem_eof_return(BIO * b,int v)258 int bio_set_mem_eof_return(BIO *b, int v) {
259     return (int)BIO_set_mem_eof_return(b, v);
260 }
261 
bio_get_fd(BIO * bio)262 int bio_get_fd(BIO *bio) {
263     return BIO_get_fd(bio, NULL);
264 }
265 %}
266 
267 %warnfilter(454) methods_fdp;
268 %threadallow bio_do_handshake;
269 %inline %{
bio_do_handshake(BIO * bio)270 int bio_do_handshake(BIO *bio) {
271     return BIO_do_handshake(bio);
272 }
273 
274 /* macro */
bio_make_bio_pair(BIO * b1,BIO * b2)275 int bio_make_bio_pair(BIO* b1, BIO* b2) {
276     return BIO_make_bio_pair(b1, b2);
277 }
278 
bio_set_write_buf_size(BIO * b,size_t size)279 int bio_set_write_buf_size(BIO* b, size_t size) {
280     return BIO_set_write_buf_size(b, size);
281 }
282 
bio_should_retry(BIO * a)283 int bio_should_retry(BIO* a) {
284     return BIO_should_retry(a);
285 }
286 
bio_should_read(BIO * a)287 int bio_should_read(BIO* a) {
288     return BIO_should_read(a);
289 }
290 
bio_should_write(BIO * a)291 int bio_should_write(BIO* a) {
292     return BIO_should_write(a);
293 }
294 
295 /* Macros for things not defined before 1.1.0 */
296 #if OPENSSL_VERSION_NUMBER < 0x10100000L
297 static BIO_METHOD *
BIO_meth_new(int type,const char * name)298 BIO_meth_new( int type, const char *name )
299 {
300     BIO_METHOD *method = malloc( sizeof(BIO_METHOD) );
301     memset( method, 0, sizeof(BIO_METHOD) );
302 
303     method->type = type;
304     method->name = name;
305 
306     return method;
307 }
308 
309 static void
BIO_meth_free(BIO_METHOD * meth)310 BIO_meth_free( BIO_METHOD *meth )
311 {
312     if ( meth == NULL ) {
313         return;
314     }
315 
316     free(meth);
317 }
318 #define BIO_meth_set_write(m, f) (m)->bwrite = (f)
319 #define BIO_meth_set_read(m, f) (m)->bread = (f)
320 #define BIO_meth_set_puts(m, f) (m)->bputs = (f)
321 #define BIO_meth_set_gets(m, f) (m)->bgets = (f)
322 #define BIO_meth_set_ctrl(m, f) (m)->ctrl = (f)
323 #define BIO_meth_set_create(m, f) (m)->create = (f)
324 #define BIO_meth_set_destroy(m, f) (m)->destroy = (f)
325 #define BIO_set_shutdown(b, x) (b)->shutdown = x
326 #define BIO_get_shutdown(b) (b)->shutdown
327 #define BIO_set_init(b, x)    b->init = x
328 #define BIO_get_init(b) (b)->init
329 #define BIO_set_data(b, x)    b->ptr = x
330 #define BIO_clear_flags(b, x)    b->flags &= ~(x)
331 #define BIO_get_data(b)    b->ptr
332 #endif
333 
334 /* implment custom BIO_s_pyfd */
335 
336 #ifdef _WIN32
337 #  define clear_sys_error()       SetLastError(0)
338 /* Linux doesn't use underscored calls yet */
339 #  define open(p, f, m) _open(p, f, m)
340 #  define read(f, b, n) _read(f, b, n)
341 #  define write(f, b, n) _write(f, b, n)
342 #  define close(f) _close(f)
343 #  define lseek(fd, o, w) _lseek(fd, o, w)
344 #else
345 # define clear_sys_error()       errno=0
346 #endif
347 
348 typedef struct pyfd_struct {
349     int fd;
350 } BIO_PYFD_CTX;
351 
352 /* Setting up methods_fdp */
353 static BIO_METHOD *methods_fdp;
354 
pyfd_write(BIO * b,const char * in,int inl)355 static int pyfd_write(BIO *b, const char *in, int inl) {
356     int ret, fd;
357 
358     if (BIO_get_fd(b, &fd) == -1) {
359         PyErr_SetString(_bio_err, "BIO has not been initialized.");
360         return -1;
361     }
362     clear_sys_error();
363     ret = write(fd, in, inl);
364     BIO_clear_retry_flags(b);
365     if (ret <= 0) {
366         if (BIO_fd_should_retry(ret))
367             BIO_set_retry_write(b);
368     }
369     return ret;
370 }
371 
pyfd_read(BIO * b,char * out,int outl)372 static int pyfd_read(BIO *b, char *out, int outl) {
373     int ret = 0, fd;
374 
375     if (BIO_get_fd(b, &fd) == -1) {
376         PyErr_SetString(_bio_err, "BIO has not been initialized.");
377         return -1;
378     }
379     if (out != NULL) {
380         clear_sys_error();
381         ret = read(fd, out, outl);
382         BIO_clear_retry_flags(b);
383         if (ret <= 0) {
384             if (BIO_fd_should_retry(ret))
385                 BIO_set_retry_read(b);
386         }
387     }
388     return ret;
389 }
390 
pyfd_puts(BIO * bp,const char * str)391 static int pyfd_puts(BIO *bp, const char *str) {
392     int n, ret;
393 
394     n = strlen(str);
395     ret = pyfd_write(bp, str, n);
396     return ret;
397 }
398 
pyfd_gets(BIO * bp,char * buf,int size)399 static int pyfd_gets(BIO *bp, char *buf, int size) {
400     int ret = 0;
401     char *ptr = buf;
402     char *end = buf + size - 1;
403 
404     /* See
405     https://github.com/openssl/openssl/pull/3442
406     We were here just repeating a bug from OpenSSL
407     */
408     while (ptr < end && pyfd_read(bp, ptr, 1) > 0) {
409         if (*ptr++ == '\n')
410            break;
411     }
412 
413     ptr[0] = '\0';
414 
415     if (buf[0] != '\0')
416         ret = strlen(buf);
417     return ret;
418 }
419 
pyfd_new(BIO * b)420 static int pyfd_new(BIO* b) {
421     BIO_PYFD_CTX* ctx;
422 
423     ctx = OPENSSL_zalloc(sizeof(*ctx));
424     if (ctx == NULL)
425         return 0;
426 
427     ctx->fd = -1;
428 
429     BIO_set_data(b, ctx);
430     BIO_set_shutdown(b, 0);
431     BIO_set_init(b, 1);
432 
433     return 1;
434     }
435 
436 #ifdef LIBRESSL_VERSION_NUMBER
437 #define BIO_get_init(b) (b)->init
438 #endif
439 
pyfd_free(BIO * b)440 static int pyfd_free(BIO* b) {
441     BIO_PYFD_CTX* ctx;
442 
443     if (b == 0)
444         return 0;
445 
446     ctx = BIO_get_data(b);
447     if (ctx == NULL)
448         return 0;
449 
450     if (BIO_get_shutdown(b) && BIO_get_init(b))
451         close(ctx->fd);
452 
453     BIO_set_data(b, NULL);
454     BIO_set_shutdown(b, 0);
455     BIO_set_init(b, 0);
456 
457     OPENSSL_free(ctx);
458 
459     return 1;
460 }
461 
pyfd_ctrl(BIO * b,int cmd,long num,void * ptr)462 static long pyfd_ctrl(BIO *b, int cmd, long num, void *ptr) {
463     BIO_PYFD_CTX* ctx;
464     int *ip;
465     long ret = 1;
466 
467     ctx = BIO_get_data(b);
468     if (ctx == NULL)
469         return 0;
470 
471     switch (cmd) {
472     case BIO_CTRL_RESET:
473         num = 0;
474     case BIO_C_FILE_SEEK:
475         ret = (long)lseek(ctx->fd, num, 0);
476         break;
477     case BIO_C_FILE_TELL:
478     case BIO_CTRL_INFO:
479         ret = (long)lseek(ctx->fd, 0, 1);
480         break;
481     case BIO_C_SET_FD:
482         pyfd_free(b);
483         if (*((int *)ptr) > -1) {
484             if (!pyfd_new(b) || !(ctx = BIO_get_data(b)))
485                 return 0;
486             ctx->fd = *((int *)ptr);
487             BIO_set_shutdown(b, (int)num);
488             BIO_set_init(b, 1);
489             }
490         break;
491     case BIO_C_GET_FD:
492         if (BIO_get_init(b)) {
493             ip = (int *)ptr;
494             if (ip != NULL)
495                 *ip = ctx->fd;
496             ret = ctx->fd;
497         } else
498             ret = -1;
499         break;
500     case BIO_CTRL_GET_CLOSE:
501         ret = BIO_get_shutdown(b);
502         break;
503     case BIO_CTRL_SET_CLOSE:
504         BIO_set_shutdown(b, (int)num);
505         break;
506     case BIO_CTRL_PENDING:
507     case BIO_CTRL_WPENDING:
508         ret = 0;
509         break;
510     case BIO_CTRL_DUP:
511     case BIO_CTRL_FLUSH:
512         ret = 1;
513         break;
514     default:
515         ret = 0;
516         break;
517     }
518     return ret;
519 }
520 
pyfd_init(void)521 void pyfd_init(void) {
522 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
523     methods_fdp = BIO_meth_new(
524         BIO_get_new_index()|BIO_TYPE_DESCRIPTOR|BIO_TYPE_SOURCE_SINK,
525         "python file descriptor");
526 #else
527     methods_fdp = BIO_meth_new(
528         100 |BIO_TYPE_DESCRIPTOR|BIO_TYPE_SOURCE_SINK,
529         "python file descriptor");
530 #endif
531 
532     BIO_meth_set_write(methods_fdp, pyfd_write);
533     BIO_meth_set_read(methods_fdp, pyfd_read);
534     BIO_meth_set_puts(methods_fdp, pyfd_puts);
535     BIO_meth_set_gets(methods_fdp, pyfd_gets);
536     BIO_meth_set_ctrl(methods_fdp, pyfd_ctrl);
537     BIO_meth_set_create(methods_fdp, pyfd_new);
538     BIO_meth_set_destroy(methods_fdp, pyfd_free);
539 }
540 
BIO_new_pyfd(int fd,int close_flag)541 BIO* BIO_new_pyfd(int fd, int close_flag) {
542     BIO *ret;
543 
544     ret = BIO_new(methods_fdp);
545     BIO_set_fd(ret, fd, close_flag);
546     return ret;
547     }
548 %}
549 
550