Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b8753e5

Browse files
committed
Replace both send and receive BIO routines in the SSL code with our own,
calling recv() and send(). This makes the calls go through the socket emulation code on Win32, making them for example properly interruptible.
1 parent 65e3ea7 commit b8753e5

File tree

1 file changed

+41
-15
lines changed

1 file changed

+41
-15
lines changed

src/backend/libpq/be-secure.c

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.87 2008/12/03 20:04:26 mha Exp $
14+
* $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.88 2008/12/14 19:39:37 mha Exp $
1515
*
1616
* Since the server static private key ($DataDir/server.key)
1717
* will normally be stored unencrypted so that the database
@@ -394,45 +394,71 @@ secure_write(Port *port, void *ptr, size_t len)
394394
#ifdef USE_SSL
395395

396396
/*
397-
* Private substitute BIO: this wraps the SSL library's standard socket BIO
398-
* so that we can enable and disable interrupts just while calling recv().
399-
* We cannot have interrupts occurring while the bulk of openssl runs,
400-
* because it uses malloc() and possibly other non-reentrant libc facilities.
397+
* Private substitute BIO: this does the sending and receiving using send() and
398+
* recv() instead. This is so that we can enable and disable interrupts
399+
* just while calling recv(). We cannot have interrupts occurring while
400+
* the bulk of openssl runs, because it uses malloc() and possibly other
401+
* non-reentrant libc facilities. We also need to call send() and recv()
402+
* directly so it gets passed through the socket/signals layer on Win32.
403+
*
404+
* They are closely modelled on the original socket implementations in OpenSSL.
401405
*
402-
* As of openssl 0.9.7, we can use the reasonably clean method of interposing
403-
* a wrapper around the standard socket BIO's sock_read() method. This relies
404-
* on the fact that sock_read() doesn't call anything non-reentrant, in fact
405-
* not much of anything at all except recv(). If this ever changes we'd
406-
* probably need to duplicate the code of sock_read() in order to push the
407-
* interrupt enable/disable down yet another level.
408406
*/
409407

410408
static bool my_bio_initialized = false;
411409
static BIO_METHOD my_bio_methods;
412-
static int (*std_sock_read) (BIO *h, char *buf, int size);
413410

414411
static int
415412
my_sock_read(BIO *h, char *buf, int size)
416413
{
417-
int res;
414+
int res = 0;
418415

419416
prepare_for_client_read();
420417

421-
res = std_sock_read(h, buf, size);
418+
if (buf != NULL)
419+
{
420+
res = recv(h->num, buf, size, 0);
421+
BIO_clear_retry_flags(h);
422+
if (res <= 0)
423+
{
424+
/* If we were interrupted, tell caller to retry */
425+
if (errno == EINTR)
426+
{
427+
BIO_set_retry_read(h);
428+
}
429+
}
430+
}
422431

423432
client_read_ended();
424433

425434
return res;
426435
}
427436

437+
static int
438+
my_sock_write(BIO *h, const char *buf, int size)
439+
{
440+
int res = 0;
441+
442+
res = send(h->num, buf, size, 0);
443+
if (res <= 0)
444+
{
445+
if (errno == EINTR)
446+
{
447+
BIO_set_retry_write(h);
448+
}
449+
}
450+
451+
return res;
452+
}
453+
428454
static BIO_METHOD *
429455
my_BIO_s_socket(void)
430456
{
431457
if (!my_bio_initialized)
432458
{
433459
memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD));
434-
std_sock_read = my_bio_methods.bread;
435460
my_bio_methods.bread = my_sock_read;
461+
my_bio_methods.bwrite = my_sock_write;
436462
my_bio_initialized = true;
437463
}
438464
return &my_bio_methods;

0 commit comments

Comments
 (0)