PostgreSQL Source Code git master
be-secure-gssapi.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * be-secure-gssapi.c
4 * GSSAPI encryption support
5 *
6 * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/backend/libpq/be-secure-gssapi.c
10 *
11 *-------------------------------------------------------------------------
12 */
13
14#include "postgres.h"
15
16#include <unistd.h>
17
18#include "libpq/auth.h"
20#include "libpq/libpq.h"
21#include "miscadmin.h"
22#include "pgstat.h"
23#include "port/pg_bswap.h"
25#include "utils/memutils.h"
26
27
28/*
29 * Handle the encryption/decryption of data using GSSAPI.
30 *
31 * In the encrypted data stream on the wire, we break up the data
32 * into packets where each packet starts with a uint32-size length
33 * word (in network byte order), then encrypted data of that length
34 * immediately following. Decryption yields the same data stream
35 * that would appear when not using encryption.
36 *
37 * Encrypted data typically ends up being larger than the same data
38 * unencrypted, so we use fixed-size buffers for handling the
39 * encryption/decryption which are larger than PQComm's buffer will
40 * typically be to minimize the times where we have to make multiple
41 * packets (and therefore multiple recv/send calls for a single
42 * read/write call to us).
43 *
44 * NOTE: The client and server have to agree on the max packet size,
45 * because we have to pass an entire packet to GSSAPI at a time and we
46 * don't want the other side to send arbitrarily huge packets as we
47 * would have to allocate memory for them to then pass them to GSSAPI.
48 *
49 * Therefore, this #define is effectively part of the protocol
50 * spec and can't ever be changed.
51 */
52#define PQ_GSS_MAX_PACKET_SIZE 16384 /* includes uint32 header word */
53
54/*
55 * However, during the authentication exchange we must cope with whatever
56 * message size the GSSAPI library wants to send (because our protocol
57 * doesn't support splitting those messages). Depending on configuration
58 * those messages might be as much as 64kB.
59 */
60#define PQ_GSS_AUTH_BUFFER_SIZE 65536 /* includes uint32 header word */
61
62/*
63 * Since we manage at most one GSS-encrypted connection per backend,
64 * we can just keep all this state in static variables. The char *
65 * variables point to buffers that are allocated once and re-used.
66 */
67static char *PqGSSSendBuffer; /* Encrypted data waiting to be sent */
68static int PqGSSSendLength; /* End of data available in PqGSSSendBuffer */
69static int PqGSSSendNext; /* Next index to send a byte from
70 * PqGSSSendBuffer */
71static int PqGSSSendConsumed; /* Number of source bytes encrypted but not
72 * yet reported as sent */
73
74static char *PqGSSRecvBuffer; /* Received, encrypted data */
75static int PqGSSRecvLength; /* End of data available in PqGSSRecvBuffer */
76
77static char *PqGSSResultBuffer; /* Decryption of data in gss_RecvBuffer */
78static int PqGSSResultLength; /* End of data available in PqGSSResultBuffer */
79static int PqGSSResultNext; /* Next index to read a byte from
80 * PqGSSResultBuffer */
81
82static uint32 PqGSSMaxPktSize; /* Maximum size we can encrypt and fit the
83 * results into our output buffer */
84
85
86/*
87 * Attempt to write len bytes of data from ptr to a GSSAPI-encrypted connection.
88 *
89 * The connection must be already set up for GSSAPI encryption (i.e., GSSAPI
90 * transport negotiation is complete).
91 *
92 * On success, returns the number of data bytes consumed (possibly less than
93 * len). On failure, returns -1 with errno set appropriately. For retryable
94 * errors, caller should call again (passing the same or more data) once the
95 * socket is ready.
96 *
97 * Dealing with fatal errors here is a bit tricky: we can't invoke elog(FATAL)
98 * since it would try to write to the client, probably resulting in infinite
99 * recursion. Instead, use elog(COMMERROR) to log extra info about the
100 * failure if necessary, and then return an errno indicating connection loss.
101 */
102ssize_t
103be_gssapi_write(Port *port, const void *ptr, size_t len)
104{
105 OM_uint32 major,
106 minor;
107 gss_buffer_desc input,
108 output;
109 size_t bytes_to_encrypt;
110 size_t bytes_encrypted;
111 gss_ctx_id_t gctx = port->gss->ctx;
112
113 /*
114 * When we get a retryable failure, we must not tell the caller we have
115 * successfully transmitted everything, else it won't retry. For
116 * simplicity, we claim we haven't transmitted anything until we have
117 * successfully transmitted all "len" bytes. Between calls, the amount of
118 * the current input data that's already been encrypted and placed into
119 * PqGSSSendBuffer (and perhaps transmitted) is remembered in
120 * PqGSSSendConsumed. On a retry, the caller *must* be sending that data
121 * again, so if it offers a len less than that, something is wrong.
122 *
123 * Note: it may seem attractive to report partial write completion once
124 * we've successfully sent any encrypted packets. However, doing that
125 * expands the state space of this processing and has been responsible for
126 * bugs in the past (cf. commit d053a879b). We won't save much,
127 * typically, by letting callers discard data early, so don't risk it.
128 */
130 {
131 elog(COMMERROR, "GSSAPI caller failed to retransmit all data needing to be retried");
132 errno = ECONNRESET;
133 return -1;
134 }
135
136 /* Discount whatever source data we already encrypted. */
137 bytes_to_encrypt = len - PqGSSSendConsumed;
138 bytes_encrypted = PqGSSSendConsumed;
139
140 /*
141 * Loop through encrypting data and sending it out until it's all done or
142 * secure_raw_write() complains (which would likely mean that the socket
143 * is non-blocking and the requested send() would block, or there was some
144 * kind of actual error).
145 */
146 while (bytes_to_encrypt || PqGSSSendLength)
147 {
148 int conf_state = 0;
149 uint32 netlen;
150
151 /*
152 * Check if we have data in the encrypted output buffer that needs to
153 * be sent (possibly left over from a previous call), and if so, try
154 * to send it. If we aren't able to, return that fact back up to the
155 * caller.
156 */
157 if (PqGSSSendLength)
158 {
159 ssize_t ret;
160 ssize_t amount = PqGSSSendLength - PqGSSSendNext;
161
163 if (ret <= 0)
164 return ret;
165
166 /*
167 * Check if this was a partial write, and if so, move forward that
168 * far in our buffer and try again.
169 */
170 if (ret < amount)
171 {
172 PqGSSSendNext += ret;
173 continue;
174 }
175
176 /* We've successfully sent whatever data was in the buffer. */
178 }
179
180 /*
181 * Check if there are any bytes left to encrypt. If not, we're done.
182 */
183 if (!bytes_to_encrypt)
184 break;
185
186 /*
187 * Check how much we are being asked to send, if it's too much, then
188 * we will have to loop and possibly be called multiple times to get
189 * through all the data.
190 */
191 if (bytes_to_encrypt > PqGSSMaxPktSize)
192 input.length = PqGSSMaxPktSize;
193 else
194 input.length = bytes_to_encrypt;
195
196 input.value = (char *) ptr + bytes_encrypted;
197
198 output.value = NULL;
199 output.length = 0;
200
201 /*
202 * Create the next encrypted packet. Any failure here is considered a
203 * hard failure, so we return -1 even if some data has been sent.
204 */
205 major = gss_wrap(&minor, gctx, 1, GSS_C_QOP_DEFAULT,
206 &input, &conf_state, &output);
207 if (major != GSS_S_COMPLETE)
208 {
209 pg_GSS_error(_("GSSAPI wrap error"), major, minor);
210 errno = ECONNRESET;
211 return -1;
212 }
213 if (conf_state == 0)
214 {
216 (errmsg("outgoing GSSAPI message would not use confidentiality")));
217 errno = ECONNRESET;
218 return -1;
219 }
220 if (output.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
221 {
223 (errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
224 (size_t) output.length,
225 PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))));
226 errno = ECONNRESET;
227 return -1;
228 }
229
230 bytes_encrypted += input.length;
231 bytes_to_encrypt -= input.length;
232 PqGSSSendConsumed += input.length;
233
234 /* 4 network-order bytes of length, then payload */
235 netlen = pg_hton32(output.length);
236 memcpy(PqGSSSendBuffer + PqGSSSendLength, &netlen, sizeof(uint32));
237 PqGSSSendLength += sizeof(uint32);
238
239 memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length);
240 PqGSSSendLength += output.length;
241
242 /* Release buffer storage allocated by GSSAPI */
243 gss_release_buffer(&minor, &output);
244 }
245
246 /* If we get here, our counters should all match up. */
248 Assert(len == bytes_encrypted);
249
250 /* We're reporting all the data as sent, so reset PqGSSSendConsumed. */
252
253 return bytes_encrypted;
254}
255
256/*
257 * Read up to len bytes of data into ptr from a GSSAPI-encrypted connection.
258 *
259 * The connection must be already set up for GSSAPI encryption (i.e., GSSAPI
260 * transport negotiation is complete).
261 *
262 * Returns the number of data bytes read, or on failure, returns -1
263 * with errno set appropriately. For retryable errors, caller should call
264 * again once the socket is ready.
265 *
266 * We treat fatal errors the same as in be_gssapi_write(), even though the
267 * argument about infinite recursion doesn't apply here.
268 */
269ssize_t
270be_gssapi_read(Port *port, void *ptr, size_t len)
271{
272 OM_uint32 major,
273 minor;
274 gss_buffer_desc input,
275 output;
276 ssize_t ret;
277 size_t bytes_returned = 0;
278 gss_ctx_id_t gctx = port->gss->ctx;
279
280 /*
281 * The plan here is to read one incoming encrypted packet into
282 * PqGSSRecvBuffer, decrypt it into PqGSSResultBuffer, and then dole out
283 * data from there to the caller. When we exhaust the current input
284 * packet, read another.
285 */
286 while (bytes_returned < len)
287 {
288 int conf_state = 0;
289
290 /* Check if we have data in our buffer that we can return immediately */
292 {
293 size_t bytes_in_buffer = PqGSSResultLength - PqGSSResultNext;
294 size_t bytes_to_copy = Min(bytes_in_buffer, len - bytes_returned);
295
296 /*
297 * Copy the data from our result buffer into the caller's buffer,
298 * at the point where we last left off filling their buffer.
299 */
300 memcpy((char *) ptr + bytes_returned, PqGSSResultBuffer + PqGSSResultNext, bytes_to_copy);
301 PqGSSResultNext += bytes_to_copy;
302 bytes_returned += bytes_to_copy;
303
304 /*
305 * At this point, we've either filled the caller's buffer or
306 * emptied our result buffer. Either way, return to caller. In
307 * the second case, we could try to read another encrypted packet,
308 * but the odds are good that there isn't one available. (If this
309 * isn't true, we chose too small a max packet size.) In any
310 * case, there's no harm letting the caller process the data we've
311 * already returned.
312 */
313 break;
314 }
315
316 /* Result buffer is empty, so reset buffer pointers */
318
319 /*
320 * Because we chose above to return immediately as soon as we emit
321 * some data, bytes_returned must be zero at this point. Therefore
322 * the failure exits below can just return -1 without worrying about
323 * whether we already emitted some data.
324 */
325 Assert(bytes_returned == 0);
326
327 /*
328 * At this point, our result buffer is empty with more bytes being
329 * requested to be read. We are now ready to load the next packet and
330 * decrypt it (entirely) into our result buffer.
331 */
332
333 /* Collect the length if we haven't already */
334 if (PqGSSRecvLength < sizeof(uint32))
335 {
337 sizeof(uint32) - PqGSSRecvLength);
338
339 /* If ret <= 0, secure_raw_read already set the correct errno */
340 if (ret <= 0)
341 return ret;
342
343 PqGSSRecvLength += ret;
344
345 /* If we still haven't got the length, return to the caller */
346 if (PqGSSRecvLength < sizeof(uint32))
347 {
348 errno = EWOULDBLOCK;
349 return -1;
350 }
351 }
352
353 /* Decode the packet length and check for overlength packet */
354 input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
355
356 if (input.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
357 {
359 (errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
360 (size_t) input.length,
361 PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))));
362 errno = ECONNRESET;
363 return -1;
364 }
365
366 /*
367 * Read as much of the packet as we are able to on this call into
368 * wherever we left off from the last time we were called.
369 */
371 input.length - (PqGSSRecvLength - sizeof(uint32)));
372 /* If ret <= 0, secure_raw_read already set the correct errno */
373 if (ret <= 0)
374 return ret;
375
376 PqGSSRecvLength += ret;
377
378 /* If we don't yet have the whole packet, return to the caller */
379 if (PqGSSRecvLength - sizeof(uint32) < input.length)
380 {
381 errno = EWOULDBLOCK;
382 return -1;
383 }
384
385 /*
386 * We now have the full packet and we can perform the decryption and
387 * refill our result buffer, then loop back up to pass data back to
388 * the caller.
389 */
390 output.value = NULL;
391 output.length = 0;
392 input.value = PqGSSRecvBuffer + sizeof(uint32);
393
394 major = gss_unwrap(&minor, gctx, &input, &output, &conf_state, NULL);
395 if (major != GSS_S_COMPLETE)
396 {
397 pg_GSS_error(_("GSSAPI unwrap error"), major, minor);
398 errno = ECONNRESET;
399 return -1;
400 }
401 if (conf_state == 0)
402 {
404 (errmsg("incoming GSSAPI message did not use confidentiality")));
405 errno = ECONNRESET;
406 return -1;
407 }
408
409 memcpy(PqGSSResultBuffer, output.value, output.length);
410 PqGSSResultLength = output.length;
411
412 /* Our receive buffer is now empty, reset it */
413 PqGSSRecvLength = 0;
414
415 /* Release buffer storage allocated by GSSAPI */
416 gss_release_buffer(&minor, &output);
417 }
418
419 return bytes_returned;
420}
421
422/*
423 * Read the specified number of bytes off the wire, waiting using
424 * WaitLatchOrSocket if we would block.
425 *
426 * Results are read into PqGSSRecvBuffer.
427 *
428 * Will always return either -1, to indicate a permanent error, or len.
429 */
430static ssize_t
432{
433 ssize_t ret;
434
435 /*
436 * Keep going until we either read in everything we were asked to, or we
437 * error out.
438 */
439 while (PqGSSRecvLength < len)
440 {
442
443 /*
444 * If we got back an error and it wasn't just
445 * EWOULDBLOCK/EAGAIN/EINTR, then give up.
446 */
447 if (ret < 0 &&
448 !(errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
449 return -1;
450
451 /*
452 * Ok, we got back either a positive value, zero, or a negative result
453 * indicating we should retry.
454 *
455 * If it was zero or negative, then we wait on the socket to be
456 * readable again.
457 */
458 if (ret <= 0)
459 {
462 port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER);
463
464 /*
465 * If we got back zero bytes, and then waited on the socket to be
466 * readable and got back zero bytes on a second read, then this is
467 * EOF and the client hung up on us.
468 *
469 * If we did get data here, then we can just fall through and
470 * handle it just as if we got data the first time.
471 *
472 * Otherwise loop back to the top and try again.
473 */
474 if (ret == 0)
475 {
477 if (ret == 0)
478 return -1;
479 }
480 if (ret < 0)
481 continue;
482 }
483
484 PqGSSRecvLength += ret;
485 }
486
487 return len;
488}
489
490/*
491 * Start up a GSSAPI-encrypted connection. This performs GSSAPI
492 * authentication; after this function completes, it is safe to call
493 * be_gssapi_read and be_gssapi_write. Returns -1 and logs on failure;
494 * otherwise, returns 0 and marks the connection as ready for GSSAPI
495 * encryption.
496 *
497 * Note that unlike the be_gssapi_read/be_gssapi_write functions, this
498 * function WILL block on the socket to be ready for read/write (using
499 * WaitLatchOrSocket) as appropriate while establishing the GSSAPI
500 * session.
501 */
502ssize_t
504{
505 bool complete_next = false;
506 OM_uint32 major,
507 minor;
508 gss_cred_id_t delegated_creds;
509
510 INJECTION_POINT("backend-gssapi-startup", NULL);
511
512 /*
513 * Allocate subsidiary Port data for GSSAPI operations.
514 */
515 port->gss = (pg_gssinfo *)
516 MemoryContextAllocZero(TopMemoryContext, sizeof(pg_gssinfo));
517
518 delegated_creds = GSS_C_NO_CREDENTIAL;
519 port->gss->delegated_creds = false;
520
521 /*
522 * Allocate buffers and initialize state variables. By malloc'ing the
523 * buffers at this point, we avoid wasting static data space in processes
524 * that will never use them, and we ensure that the buffers are
525 * sufficiently aligned for the length-word accesses that we do in some
526 * places in this file.
527 *
528 * We'll use PQ_GSS_AUTH_BUFFER_SIZE-sized buffers until transport
529 * negotiation is complete, then switch to PQ_GSS_MAX_PACKET_SIZE.
530 */
536 (errcode(ERRCODE_OUT_OF_MEMORY),
537 errmsg("out of memory")));
540
541 /*
542 * Use the configured keytab, if there is one. As we now require MIT
543 * Kerberos, we might consider using the credential store extensions in
544 * the future instead of the environment variable.
545 */
546 if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
547 {
548 if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
549 {
550 /* The only likely failure cause is OOM, so use that errcode */
552 (errcode(ERRCODE_OUT_OF_MEMORY),
553 errmsg("could not set environment: %m")));
554 }
555 }
556
557 while (true)
558 {
559 ssize_t ret;
560 gss_buffer_desc input,
561 output = GSS_C_EMPTY_BUFFER;
562
563 /*
564 * The client always sends first, so try to go ahead and read the
565 * length and wait on the socket to be readable again if that fails.
566 */
567 ret = read_or_wait(port, sizeof(uint32));
568 if (ret < 0)
569 return ret;
570
571 /*
572 * Get the length for this packet from the length header.
573 */
574 input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
575
576 /* Done with the length, reset our buffer */
577 PqGSSRecvLength = 0;
578
579 /*
580 * During initialization, packets are always fully consumed and
581 * shouldn't ever be over PQ_GSS_AUTH_BUFFER_SIZE in total length.
582 *
583 * Verify on our side that the client doesn't do something funny.
584 */
585 if (input.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
586 {
588 (errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
589 (size_t) input.length,
590 PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))));
591 return -1;
592 }
593
594 /*
595 * Get the rest of the packet so we can pass it to GSSAPI to accept
596 * the context.
597 */
598 ret = read_or_wait(port, input.length);
599 if (ret < 0)
600 return ret;
601
602 input.value = PqGSSRecvBuffer;
603
604 /* Process incoming data. (The client sends first.) */
605 major = gss_accept_sec_context(&minor, &port->gss->ctx,
606 GSS_C_NO_CREDENTIAL, &input,
607 GSS_C_NO_CHANNEL_BINDINGS,
608 &port->gss->name, NULL, &output, NULL,
609 NULL, pg_gss_accept_delegation ? &delegated_creds : NULL);
610
611 if (GSS_ERROR(major))
612 {
613 pg_GSS_error(_("could not accept GSSAPI security context"),
614 major, minor);
615 gss_release_buffer(&minor, &output);
616 return -1;
617 }
618 else if (!(major & GSS_S_CONTINUE_NEEDED))
619 {
620 /*
621 * rfc2744 technically permits context negotiation to be complete
622 * both with and without a packet to be sent.
623 */
624 complete_next = true;
625 }
626
627 if (delegated_creds != GSS_C_NO_CREDENTIAL)
628 {
629 pg_store_delegated_credential(delegated_creds);
630 port->gss->delegated_creds = true;
631 }
632
633 /* Done handling the incoming packet, reset our buffer */
634 PqGSSRecvLength = 0;
635
636 /*
637 * Check if we have data to send and, if we do, make sure to send it
638 * all
639 */
640 if (output.length > 0)
641 {
642 uint32 netlen = pg_hton32(output.length);
643
644 if (output.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
645 {
647 (errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
648 (size_t) output.length,
649 PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))));
650 gss_release_buffer(&minor, &output);
651 return -1;
652 }
653
654 memcpy(PqGSSSendBuffer, &netlen, sizeof(uint32));
655 PqGSSSendLength += sizeof(uint32);
656
657 memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length);
658 PqGSSSendLength += output.length;
659
660 /* we don't bother with PqGSSSendConsumed here */
661
663 {
666
667 /*
668 * If we got back an error and it wasn't just
669 * EWOULDBLOCK/EAGAIN/EINTR, then give up.
670 */
671 if (ret < 0 &&
672 !(errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
673 {
674 gss_release_buffer(&minor, &output);
675 return -1;
676 }
677
678 /* Wait and retry if we couldn't write yet */
679 if (ret <= 0)
680 {
683 port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER);
684 continue;
685 }
686
687 PqGSSSendNext += ret;
688 }
689
690 /* Done sending the packet, reset our buffer */
692
693 gss_release_buffer(&minor, &output);
694 }
695
696 /*
697 * If we got back that the connection is finished being set up, now
698 * that we've sent the last packet, exit our loop.
699 */
700 if (complete_next)
701 break;
702 }
703
704 /*
705 * Release the large authentication buffers and allocate the ones we want
706 * for normal operation.
707 */
716 (errcode(ERRCODE_OUT_OF_MEMORY),
717 errmsg("out of memory")));
720
721 /*
722 * Determine the max packet size which will fit in our buffer, after
723 * accounting for the length. be_gssapi_write will need this.
724 */
725 major = gss_wrap_size_limit(&minor, port->gss->ctx, 1, GSS_C_QOP_DEFAULT,
728
729 if (GSS_ERROR(major))
730 {
731 pg_GSS_error(_("GSSAPI size check error"), major, minor);
732 return -1;
733 }
734
735 port->gss->enc = true;
736
737 return 0;
738}
739
740/*
741 * Return if GSSAPI authentication was used on this connection.
742 */
743bool
745{
746 if (!port || !port->gss)
747 return false;
748
749 return port->gss->auth;
750}
751
752/*
753 * Return if GSSAPI encryption is enabled and being used on this connection.
754 */
755bool
757{
758 if (!port || !port->gss)
759 return false;
760
761 return port->gss->enc;
762}
763
764/*
765 * Return the GSSAPI principal used for authentication on this connection
766 * (NULL if we did not perform GSSAPI authentication).
767 */
768const char *
770{
771 if (!port || !port->gss)
772 return NULL;
773
774 return port->gss->princ;
775}
776
777/*
778 * Return if GSSAPI delegated credentials were included on this
779 * connection.
780 */
781bool
783{
784 if (!port || !port->gss)
785 return false;
786
787 return port->gss->delegated_creds;
788}
char * pg_krb_server_keyfile
Definition: auth.c:173
bool pg_gss_accept_delegation
Definition: auth.c:175
void pg_store_delegated_credential(gss_cred_id_t cred)
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
static int PqGSSRecvLength
static int PqGSSResultLength
#define PQ_GSS_AUTH_BUFFER_SIZE
static char * PqGSSSendBuffer
ssize_t be_gssapi_write(Port *port, const void *ptr, size_t len)
bool be_gssapi_get_auth(Port *port)
static int PqGSSSendConsumed
ssize_t be_gssapi_read(Port *port, void *ptr, size_t len)
static ssize_t read_or_wait(Port *port, ssize_t len)
ssize_t secure_open_gssapi(Port *port)
static char * PqGSSRecvBuffer
static int PqGSSResultNext
static uint32 PqGSSMaxPktSize
bool be_gssapi_get_enc(Port *port)
static int PqGSSSendLength
static int PqGSSSendNext
static char * PqGSSResultBuffer
#define PQ_GSS_MAX_PACKET_SIZE
const char * be_gssapi_get_princ(Port *port)
bool be_gssapi_get_delegation(Port *port)
ssize_t secure_raw_read(Port *port, void *ptr, size_t len)
Definition: be-secure.c:268
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition: be-secure.c:377
#define Min(x, y)
Definition: c.h:1008
uint32_t uint32
Definition: c.h:543
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define _(x)
Definition: elog.c:91
#define COMMERROR
Definition: elog.h:33
#define FATAL
Definition: elog.h:41
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
FILE * input
FILE * output
#define INJECTION_POINT(name, arg)
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition: latch.c:223
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1263
MemoryContext TopMemoryContext
Definition: mcxt.c:166
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
#define pg_hton32(x)
Definition: pg_bswap.h:121
const void size_t len
static int port
Definition: pg_regress.c:115
Definition: libpq-be.h:129
#define WL_SOCKET_READABLE
Definition: waiteventset.h:35
#define WL_EXIT_ON_PM_DEATH
Definition: waiteventset.h:39
#define WL_SOCKET_WRITEABLE
Definition: waiteventset.h:36
#define EINTR
Definition: win32_port.h:364
#define EWOULDBLOCK
Definition: win32_port.h:370
#define setenv(x, y, z)
Definition: win32_port.h:545
#define ECONNRESET
Definition: win32_port.h:374
#define EAGAIN
Definition: win32_port.h:362