|
11 | 11 | *
|
12 | 12 | *
|
13 | 13 | * 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 $ |
15 | 15 | *
|
16 | 16 | * Since the server static private key ($DataDir/server.key)
|
17 | 17 | * will normally be stored unencrypted so that the database
|
@@ -394,45 +394,71 @@ secure_write(Port *port, void *ptr, size_t len)
|
394 | 394 | #ifdef USE_SSL
|
395 | 395 |
|
396 | 396 | /*
|
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. |
401 | 405 | *
|
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. |
408 | 406 | */
|
409 | 407 |
|
410 | 408 | static bool my_bio_initialized = false;
|
411 | 409 | static BIO_METHOD my_bio_methods;
|
412 |
| -static int (*std_sock_read) (BIO *h, char *buf, int size); |
413 | 410 |
|
414 | 411 | static int
|
415 | 412 | my_sock_read(BIO *h, char *buf, int size)
|
416 | 413 | {
|
417 |
| - int res; |
| 414 | + int res = 0; |
418 | 415 |
|
419 | 416 | prepare_for_client_read();
|
420 | 417 |
|
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 | + } |
422 | 431 |
|
423 | 432 | client_read_ended();
|
424 | 433 |
|
425 | 434 | return res;
|
426 | 435 | }
|
427 | 436 |
|
| 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 | + |
428 | 454 | static BIO_METHOD *
|
429 | 455 | my_BIO_s_socket(void)
|
430 | 456 | {
|
431 | 457 | if (!my_bio_initialized)
|
432 | 458 | {
|
433 | 459 | memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD));
|
434 |
| - std_sock_read = my_bio_methods.bread; |
435 | 460 | my_bio_methods.bread = my_sock_read;
|
| 461 | + my_bio_methods.bwrite = my_sock_write; |
436 | 462 | my_bio_initialized = true;
|
437 | 463 | }
|
438 | 464 | return &my_bio_methods;
|
|
0 commit comments