PostgreSQL Source Code git master
Loading...
Searching...
No Matches
be-secure-gssapi.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "libpq/auth.h"
#include "libpq/be-gssapi-common.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/pg_bswap.h"
#include "utils/injection_point.h"
#include "utils/memutils.h"
Include dependency graph for be-secure-gssapi.c:

Go to the source code of this file.

Macros

#define PQ_GSS_MAX_PACKET_SIZE   16384 /* includes uint32 header word */
 
#define PQ_GSS_AUTH_BUFFER_SIZE   65536 /* includes uint32 header word */
 

Functions

ssize_t be_gssapi_write (Port *port, const void *ptr, size_t len)
 
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)
 
bool be_gssapi_get_auth (Port *port)
 
bool be_gssapi_get_enc (Port *port)
 
const charbe_gssapi_get_princ (Port *port)
 
bool be_gssapi_get_delegation (Port *port)
 

Variables

static charPqGSSSendBuffer
 
static int PqGSSSendLength
 
static int PqGSSSendNext
 
static int PqGSSSendConsumed
 
static charPqGSSRecvBuffer
 
static int PqGSSRecvLength
 
static charPqGSSResultBuffer
 
static int PqGSSResultLength
 
static int PqGSSResultNext
 
static uint32 PqGSSMaxPktSize
 

Macro Definition Documentation

◆ PQ_GSS_AUTH_BUFFER_SIZE

#define PQ_GSS_AUTH_BUFFER_SIZE   65536 /* includes uint32 header word */

Definition at line 60 of file be-secure-gssapi.c.

◆ PQ_GSS_MAX_PACKET_SIZE

#define PQ_GSS_MAX_PACKET_SIZE   16384 /* includes uint32 header word */

Definition at line 52 of file be-secure-gssapi.c.

Function Documentation

◆ be_gssapi_get_auth()

bool be_gssapi_get_auth ( Port port)

Definition at line 744 of file be-secure-gssapi.c.

745{
746 if (!port || !port->gss)
747 return false;
748
749 return port->gss->auth;
750}
static int port
Definition pg_regress.c:115

References port.

Referenced by PerformAuthentication(), and pgstat_bestart_security().

◆ be_gssapi_get_delegation()

bool be_gssapi_get_delegation ( Port port)

Definition at line 782 of file be-secure-gssapi.c.

783{
784 if (!port || !port->gss)
785 return false;
786
787 return port->gss->delegated_creds;
788}

References port.

Referenced by check_conn_params(), dblink_connstr_check(), dblink_security_check(), PerformAuthentication(), pgfdw_security_check(), and pgstat_bestart_security().

◆ be_gssapi_get_enc()

bool be_gssapi_get_enc ( Port port)

Definition at line 756 of file be-secure-gssapi.c.

757{
758 if (!port || !port->gss)
759 return false;
760
761 return port->gss->enc;
762}

References port.

Referenced by PerformAuthentication(), and pgstat_bestart_security().

◆ be_gssapi_get_princ()

const char * be_gssapi_get_princ ( Port port)

Definition at line 769 of file be-secure-gssapi.c.

770{
771 if (!port || !port->gss)
772 return NULL;
773
774 return port->gss->princ;
775}
static int fb(int x)

References fb(), and port.

Referenced by PerformAuthentication(), and pgstat_bestart_security().

◆ be_gssapi_read()

ssize_t be_gssapi_read ( Port port,
void ptr,
size_t  len 
)

Definition at line 270 of file be-secure-gssapi.c.

271{
273 minor;
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 {
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 */
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 */
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 {
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))));
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 {
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
395 if (major != GSS_S_COMPLETE)
396 {
397 pg_GSS_error(_("GSSAPI unwrap error"), major, minor);
399 return -1;
400 }
401 if (conf_state == 0)
402 {
404 (errmsg("incoming GSSAPI message did not use confidentiality")));
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 */
417 }
418
419 return bytes_returned;
420}
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
static int PqGSSRecvLength
static int PqGSSResultLength
static char * PqGSSRecvBuffer
static int PqGSSResultNext
static char * PqGSSResultBuffer
#define PQ_GSS_MAX_PACKET_SIZE
ssize_t secure_raw_read(Port *port, void *ptr, size_t len)
Definition be-secure.c:268
#define Min(x, y)
Definition c.h:997
#define Assert(condition)
Definition c.h:873
uint32_t uint32
Definition c.h:546
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define _(x)
Definition elog.c:91
#define COMMERROR
Definition elog.h:33
#define ereport(elevel,...)
Definition elog.h:150
FILE * input
FILE * output
#define pg_ntoh32(x)
Definition pg_bswap.h:125
const void size_t len
#define EWOULDBLOCK
Definition win32_port.h:367
#define ECONNRESET
Definition win32_port.h:371

References _, Assert, COMMERROR, ECONNRESET, ereport, errmsg(), EWOULDBLOCK, fb(), input, len, Min, output, pg_GSS_error(), pg_ntoh32, port, PQ_GSS_MAX_PACKET_SIZE, PqGSSRecvBuffer, PqGSSRecvLength, PqGSSResultBuffer, PqGSSResultLength, PqGSSResultNext, and secure_raw_read().

Referenced by secure_read().

◆ be_gssapi_write()

ssize_t be_gssapi_write ( Port port,
const void ptr,
size_t  len 
)

Definition at line 103 of file be-secure-gssapi.c.

104{
106 minor;
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");
133 return -1;
134 }
135
136 /* Discount whatever source data we already encrypted. */
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 */
147 {
148 int conf_state = 0;
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;
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 */
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 */
206 &input, &conf_state, &output);
207 if (major != GSS_S_COMPLETE)
208 {
209 pg_GSS_error(_("GSSAPI wrap error"), major, minor);
211 return -1;
212 }
213 if (conf_state == 0)
214 {
216 (errmsg("outgoing GSSAPI message would not use confidentiality")));
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))));
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);
237 PqGSSSendLength += sizeof(uint32);
238
240 PqGSSSendLength += output.length;
241
242 /* Release buffer storage allocated by GSSAPI */
244 }
245
246 /* If we get here, our counters should all match up. */
249
250 /* We're reporting all the data as sent, so reset PqGSSSendConsumed. */
252
253 return bytes_encrypted;
254}
static char * PqGSSSendBuffer
static int PqGSSSendConsumed
static uint32 PqGSSMaxPktSize
static int PqGSSSendLength
static int PqGSSSendNext
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition be-secure.c:377
#define elog(elevel,...)
Definition elog.h:226
#define pg_hton32(x)
Definition pg_bswap.h:121

References _, Assert, COMMERROR, ECONNRESET, elog, ereport, errmsg(), fb(), input, len, output, pg_GSS_error(), pg_hton32, port, PQ_GSS_MAX_PACKET_SIZE, PqGSSMaxPktSize, PqGSSSendBuffer, PqGSSSendConsumed, PqGSSSendLength, PqGSSSendNext, and secure_raw_write().

Referenced by secure_write().

◆ read_or_wait()

static ssize_t read_or_wait ( Port port,
ssize_t  len 
)
static

Definition at line 431 of file be-secure-gssapi.c.

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 {
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}
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition latch.c:223
#define WL_SOCKET_READABLE
#define WL_EXIT_ON_PM_DEATH
#define EINTR
Definition win32_port.h:361
#define EAGAIN
Definition win32_port.h:359

References EAGAIN, EINTR, EWOULDBLOCK, fb(), len, port, PqGSSRecvBuffer, PqGSSRecvLength, secure_raw_read(), WaitLatchOrSocket(), WL_EXIT_ON_PM_DEATH, and WL_SOCKET_READABLE.

Referenced by secure_open_gssapi().

◆ secure_open_gssapi()

ssize_t secure_open_gssapi ( Port port)

Definition at line 503 of file be-secure-gssapi.c.

504{
505 bool complete_next = false;
507 minor;
509
510 INJECTION_POINT("backend-gssapi-startup", NULL);
511
512 /*
513 * Allocate subsidiary Port data for GSSAPI operations.
514 */
515 port->gss = (pg_gssinfo *)
517
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 */
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 */
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 */
553 errmsg("could not set environment: %m")));
554 }
555 }
556
557 while (true)
558 {
559 ssize_t ret;
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,
608 &port->gss->name, NULL, &output, NULL,
610
611 if (GSS_ERROR(major))
612 {
613 pg_GSS_error(_("could not accept GSSAPI security context"),
614 major, minor);
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
628 {
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))));
651 return -1;
652 }
653
655 PqGSSSendLength += sizeof(uint32);
656
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 {
675 return -1;
676 }
677
678 /* Wait and retry if we couldn't write yet */
679 if (ret <= 0)
680 {
684 continue;
685 }
686
687 PqGSSSendNext += ret;
688 }
689
690 /* Done sending the packet, reset our buffer */
692
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 */
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 */
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}
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)
#define PQ_GSS_AUTH_BUFFER_SIZE
static ssize_t read_or_wait(Port *port, ssize_t len)
int errcode(int sqlerrcode)
Definition elog.c:863
#define FATAL
Definition elog.h:41
#define INJECTION_POINT(name, arg)
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1266
MemoryContext TopMemoryContext
Definition mcxt.c:166
#define free(a)
#define malloc(a)
#define WL_SOCKET_WRITEABLE
#define setenv(x, y, z)
Definition win32_port.h:542

References _, COMMERROR, EAGAIN, EINTR, ereport, errcode(), errmsg(), EWOULDBLOCK, FATAL, fb(), free, INJECTION_POINT, input, malloc, MemoryContextAllocZero(), output, pg_gss_accept_delegation, pg_GSS_error(), pg_hton32, pg_krb_server_keyfile, pg_ntoh32, pg_store_delegated_credential(), port, PQ_GSS_AUTH_BUFFER_SIZE, PQ_GSS_MAX_PACKET_SIZE, PqGSSMaxPktSize, PqGSSRecvBuffer, PqGSSRecvLength, PqGSSResultBuffer, PqGSSResultLength, PqGSSResultNext, PqGSSSendBuffer, PqGSSSendConsumed, PqGSSSendLength, PqGSSSendNext, read_or_wait(), secure_raw_write(), setenv, TopMemoryContext, WaitLatchOrSocket(), WL_EXIT_ON_PM_DEATH, and WL_SOCKET_WRITEABLE.

Referenced by ProcessStartupPacket().

Variable Documentation

◆ PqGSSMaxPktSize

uint32 PqGSSMaxPktSize
static

Definition at line 82 of file be-secure-gssapi.c.

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSRecvBuffer

char* PqGSSRecvBuffer
static

Definition at line 74 of file be-secure-gssapi.c.

Referenced by be_gssapi_read(), read_or_wait(), and secure_open_gssapi().

◆ PqGSSRecvLength

int PqGSSRecvLength
static

Definition at line 75 of file be-secure-gssapi.c.

Referenced by be_gssapi_read(), read_or_wait(), and secure_open_gssapi().

◆ PqGSSResultBuffer

char* PqGSSResultBuffer
static

Definition at line 77 of file be-secure-gssapi.c.

Referenced by be_gssapi_read(), and secure_open_gssapi().

◆ PqGSSResultLength

int PqGSSResultLength
static

Definition at line 78 of file be-secure-gssapi.c.

Referenced by be_gssapi_read(), and secure_open_gssapi().

◆ PqGSSResultNext

int PqGSSResultNext
static

Definition at line 79 of file be-secure-gssapi.c.

Referenced by be_gssapi_read(), and secure_open_gssapi().

◆ PqGSSSendBuffer

char* PqGSSSendBuffer
static

Definition at line 67 of file be-secure-gssapi.c.

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSSendConsumed

int PqGSSSendConsumed
static

Definition at line 71 of file be-secure-gssapi.c.

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSSendLength

int PqGSSSendLength
static

Definition at line 68 of file be-secure-gssapi.c.

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSSendNext

int PqGSSSendNext
static

Definition at line 69 of file be-secure-gssapi.c.

Referenced by be_gssapi_write(), and secure_open_gssapi().