* Negotiate GSSAPI transport for a connection. When complete, returns * PGRES_POLLING_OK. Will return PGRES_POLLING_READING or * PGRES_POLLING_WRITING as appropriate whenever it would block, and * PGRES_POLLING_FAILED if transport could not be negotiated. */
| 484 | * PGRES_POLLING_FAILED if transport could not be negotiated. |
| 485 | */ |
| 486 | PostgresPollingStatusType |
| 487 | pqsecure_open_gss(PGconn *conn) |
| 488 | { |
| 489 | ssize_t ret; |
| 490 | OM_uint32 major, |
| 491 | minor; |
| 492 | uint32 netlen; |
| 493 | PostgresPollingStatusType result; |
| 494 | gss_buffer_desc input = GSS_C_EMPTY_BUFFER, |
| 495 | output = GSS_C_EMPTY_BUFFER; |
| 496 | |
| 497 | /* |
| 498 | * If first time through for this connection, allocate buffers and |
| 499 | * initialize state variables. By malloc'ing the buffers separately, we |
| 500 | * ensure that they are sufficiently aligned for the length-word accesses |
| 501 | * that we do in some places in this file. |
| 502 | */ |
| 503 | if (PqGSSSendBuffer == NULL) |
| 504 | { |
| 505 | PqGSSSendBuffer = malloc(PQ_GSS_SEND_BUFFER_SIZE); |
| 506 | PqGSSRecvBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); |
| 507 | PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); |
| 508 | if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer) |
| 509 | { |
| 510 | appendPQExpBufferStr(&conn->errorMessage, |
| 511 | libpq_gettext("out of memory\n")); |
| 512 | return PGRES_POLLING_FAILED; |
| 513 | } |
| 514 | PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0; |
| 515 | PqGSSRecvLength = PqGSSResultLength = PqGSSResultNext = 0; |
| 516 | } |
| 517 | |
| 518 | /* |
| 519 | * Check if we have anything to send from a prior call and if so, send it. |
| 520 | */ |
| 521 | if (PqGSSSendLength) |
| 522 | { |
| 523 | ssize_t amount = PqGSSSendLength - PqGSSSendNext; |
| 524 | |
| 525 | ret = pqsecure_raw_write(conn, PqGSSSendBuffer + PqGSSSendNext, amount); |
| 526 | if (ret < 0) |
| 527 | { |
| 528 | if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) |
| 529 | return PGRES_POLLING_WRITING; |
| 530 | else |
| 531 | return PGRES_POLLING_FAILED; |
| 532 | } |
| 533 | |
| 534 | if (ret < amount) |
| 535 | { |
| 536 | PqGSSSendNext += ret; |
| 537 | return PGRES_POLLING_WRITING; |
| 538 | } |
| 539 | |
| 540 | PqGSSSendLength = PqGSSSendNext = 0; |
| 541 | } |
| 542 | |
| 543 | /* |
no test coverage detected