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 "storage/latch.h"
#include "utils/injection_point.h"
#include "utils/memutils.h"
#include "utils/wait_event.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 62 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 54 of file be-secure-gssapi.c.

Function Documentation

◆ be_gssapi_get_auth()

bool be_gssapi_get_auth ( Port port)

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

747{
748 if (!port || !port->gss)
749 return false;
750
751 return port->gss->auth;
752}
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 784 of file be-secure-gssapi.c.

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

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 758 of file be-secure-gssapi.c.

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

References port.

Referenced by PerformAuthentication(), and pgstat_bestart_security().

◆ be_gssapi_get_princ()

const char * be_gssapi_get_princ ( Port port)

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

772{
773 if (!port || !port->gss)
774 return NULL;
775
776 return port->gss->princ;
777}
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 272 of file be-secure-gssapi.c.

273{
275 minor;
277 output;
278 ssize_t ret;
279 size_t bytes_returned = 0;
280 gss_ctx_id_t gctx = port->gss->ctx;
281
282 /*
283 * The plan here is to read one incoming encrypted packet into
284 * PqGSSRecvBuffer, decrypt it into PqGSSResultBuffer, and then dole out
285 * data from there to the caller. When we exhaust the current input
286 * packet, read another.
287 */
288 while (bytes_returned < len)
289 {
290 int conf_state = 0;
291
292 /* Check if we have data in our buffer that we can return immediately */
294 {
297
298 /*
299 * Copy the data from our result buffer into the caller's buffer,
300 * at the point where we last left off filling their buffer.
301 */
305
306 /*
307 * At this point, we've either filled the caller's buffer or
308 * emptied our result buffer. Either way, return to caller. In
309 * the second case, we could try to read another encrypted packet,
310 * but the odds are good that there isn't one available. (If this
311 * isn't true, we chose too small a max packet size.) In any
312 * case, there's no harm letting the caller process the data we've
313 * already returned.
314 */
315 break;
316 }
317
318 /* Result buffer is empty, so reset buffer pointers */
320
321 /*
322 * Because we chose above to return immediately as soon as we emit
323 * some data, bytes_returned must be zero at this point. Therefore
324 * the failure exits below can just return -1 without worrying about
325 * whether we already emitted some data.
326 */
328
329 /*
330 * At this point, our result buffer is empty with more bytes being
331 * requested to be read. We are now ready to load the next packet and
332 * decrypt it (entirely) into our result buffer.
333 */
334
335 /* Collect the length if we haven't already */
336 if (PqGSSRecvLength < sizeof(uint32))
337 {
339 sizeof(uint32) - PqGSSRecvLength);
340
341 /* If ret <= 0, secure_raw_read already set the correct errno */
342 if (ret <= 0)
343 return ret;
344
345 PqGSSRecvLength += ret;
346
347 /* If we still haven't got the length, return to the caller */
348 if (PqGSSRecvLength < sizeof(uint32))
349 {
351 return -1;
352 }
353 }
354
355 /* Decode the packet length and check for overlength packet */
356 input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
357
358 if (input.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
359 {
361 (errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
362 (size_t) input.length,
363 PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))));
365 return -1;
366 }
367
368 /*
369 * Read as much of the packet as we are able to on this call into
370 * wherever we left off from the last time we were called.
371 */
373 input.length - (PqGSSRecvLength - sizeof(uint32)));
374 /* If ret <= 0, secure_raw_read already set the correct errno */
375 if (ret <= 0)
376 return ret;
377
378 PqGSSRecvLength += ret;
379
380 /* If we don't yet have the whole packet, return to the caller */
381 if (PqGSSRecvLength - sizeof(uint32) < input.length)
382 {
384 return -1;
385 }
386
387 /*
388 * We now have the full packet and we can perform the decryption and
389 * refill our result buffer, then loop back up to pass data back to
390 * the caller.
391 */
392 output.value = NULL;
393 output.length = 0;
394 input.value = PqGSSRecvBuffer + sizeof(uint32);
395
397 if (major != GSS_S_COMPLETE)
398 {
399 pg_GSS_error(_("GSSAPI unwrap error"), major, minor);
401 return -1;
402 }
403 if (conf_state == 0)
404 {
406 (errmsg("incoming GSSAPI message did not use confidentiality")));
408 return -1;
409 }
410
411 memcpy(PqGSSResultBuffer, output.value, output.length);
412 PqGSSResultLength = output.length;
413
414 /* Our receive buffer is now empty, reset it */
415 PqGSSRecvLength = 0;
416
417 /* Release buffer storage allocated by GSSAPI */
419 }
420
421 return bytes_returned;
422}
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:269
#define Min(x, y)
Definition c.h:1054
#define Assert(condition)
Definition c.h:906
uint32_t uint32
Definition c.h:579
#define _(x)
Definition elog.c:95
#define COMMERROR
Definition elog.h:33
#define ereport(elevel,...)
Definition elog.h:150
FILE * input
FILE * output
static char * errmsg
#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 105 of file be-secure-gssapi.c.

106{
108 minor;
110 output;
111 size_t bytes_to_encrypt;
112 size_t bytes_encrypted;
113 gss_ctx_id_t gctx = port->gss->ctx;
114
115 /*
116 * When we get a retryable failure, we must not tell the caller we have
117 * successfully transmitted everything, else it won't retry. For
118 * simplicity, we claim we haven't transmitted anything until we have
119 * successfully transmitted all "len" bytes. Between calls, the amount of
120 * the current input data that's already been encrypted and placed into
121 * PqGSSSendBuffer (and perhaps transmitted) is remembered in
122 * PqGSSSendConsumed. On a retry, the caller *must* be sending that data
123 * again, so if it offers a len less than that, something is wrong.
124 *
125 * Note: it may seem attractive to report partial write completion once
126 * we've successfully sent any encrypted packets. However, doing that
127 * expands the state space of this processing and has been responsible for
128 * bugs in the past (cf. commit d053a879b). We won't save much,
129 * typically, by letting callers discard data early, so don't risk it.
130 */
132 {
133 elog(COMMERROR, "GSSAPI caller failed to retransmit all data needing to be retried");
135 return -1;
136 }
137
138 /* Discount whatever source data we already encrypted. */
141
142 /*
143 * Loop through encrypting data and sending it out until it's all done or
144 * secure_raw_write() complains (which would likely mean that the socket
145 * is non-blocking and the requested send() would block, or there was some
146 * kind of actual error).
147 */
149 {
150 int conf_state = 0;
152
153 /*
154 * Check if we have data in the encrypted output buffer that needs to
155 * be sent (possibly left over from a previous call), and if so, try
156 * to send it. If we aren't able to, return that fact back up to the
157 * caller.
158 */
159 if (PqGSSSendLength)
160 {
161 ssize_t ret;
163
165 if (ret <= 0)
166 return ret;
167
168 /*
169 * Check if this was a partial write, and if so, move forward that
170 * far in our buffer and try again.
171 */
172 if (ret < amount)
173 {
174 PqGSSSendNext += ret;
175 continue;
176 }
177
178 /* We've successfully sent whatever data was in the buffer. */
180 }
181
182 /*
183 * Check if there are any bytes left to encrypt. If not, we're done.
184 */
185 if (!bytes_to_encrypt)
186 break;
187
188 /*
189 * Check how much we are being asked to send, if it's too much, then
190 * we will have to loop and possibly be called multiple times to get
191 * through all the data.
192 */
194 input.length = PqGSSMaxPktSize;
195 else
196 input.length = bytes_to_encrypt;
197
198 input.value = (char *) ptr + bytes_encrypted;
199
200 output.value = NULL;
201 output.length = 0;
202
203 /*
204 * Create the next encrypted packet. Any failure here is considered a
205 * hard failure, so we return -1 even if some data has been sent.
206 */
208 &input, &conf_state, &output);
209 if (major != GSS_S_COMPLETE)
210 {
211 pg_GSS_error(_("GSSAPI wrap error"), major, minor);
213 return -1;
214 }
215 if (conf_state == 0)
216 {
218 (errmsg("outgoing GSSAPI message would not use confidentiality")));
220 return -1;
221 }
222 if (output.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))
223 {
225 (errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
226 (size_t) output.length,
227 PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32))));
229 return -1;
230 }
231
232 bytes_encrypted += input.length;
233 bytes_to_encrypt -= input.length;
234 PqGSSSendConsumed += input.length;
235
236 /* 4 network-order bytes of length, then payload */
237 netlen = pg_hton32(output.length);
239 PqGSSSendLength += sizeof(uint32);
240
242 PqGSSSendLength += output.length;
243
244 /* Release buffer storage allocated by GSSAPI */
246 }
247
248 /* If we get here, our counters should all match up. */
251
252 /* We're reporting all the data as sent, so reset PqGSSSendConsumed. */
254
255 return bytes_encrypted;
256}
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:378
#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 433 of file be-secure-gssapi.c.

434{
435 ssize_t ret;
436
437 /*
438 * Keep going until we either read in everything we were asked to, or we
439 * error out.
440 */
441 while (PqGSSRecvLength < len)
442 {
444
445 /*
446 * If we got back an error and it wasn't just
447 * EWOULDBLOCK/EAGAIN/EINTR, then give up.
448 */
449 if (ret < 0 &&
450 !(errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
451 return -1;
452
453 /*
454 * Ok, we got back either a positive value, zero, or a negative result
455 * indicating we should retry.
456 *
457 * If it was zero or negative, then we wait on the socket to be
458 * readable again.
459 */
460 if (ret <= 0)
461 {
465
466 /*
467 * If we got back zero bytes, and then waited on the socket to be
468 * readable and got back zero bytes on a second read, then this is
469 * EOF and the client hung up on us.
470 *
471 * If we did get data here, then we can just fall through and
472 * handle it just as if we got data the first time.
473 *
474 * Otherwise loop back to the top and try again.
475 */
476 if (ret == 0)
477 {
479 if (ret == 0)
480 return -1;
481 }
482 if (ret < 0)
483 continue;
484 }
485
486 PqGSSRecvLength += ret;
487 }
488
489 return len;
490}
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 505 of file be-secure-gssapi.c.

506{
507 bool complete_next = false;
509 minor;
511
512 INJECTION_POINT("backend-gssapi-startup", NULL);
513
514 /*
515 * Allocate subsidiary Port data for GSSAPI operations.
516 */
517 port->gss = (pg_gssinfo *)
519
521 port->gss->delegated_creds = false;
522
523 /*
524 * Allocate buffers and initialize state variables. By malloc'ing the
525 * buffers at this point, we avoid wasting static data space in processes
526 * that will never use them, and we ensure that the buffers are
527 * sufficiently aligned for the length-word accesses that we do in some
528 * places in this file.
529 *
530 * We'll use PQ_GSS_AUTH_BUFFER_SIZE-sized buffers until transport
531 * negotiation is complete, then switch to PQ_GSS_MAX_PACKET_SIZE.
532 */
539 errmsg("out of memory")));
542
543 /*
544 * Use the configured keytab, if there is one. As we now require MIT
545 * Kerberos, we might consider using the credential store extensions in
546 * the future instead of the environment variable.
547 */
549 {
550 if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
551 {
552 /* The only likely failure cause is OOM, so use that errcode */
555 errmsg("could not set environment: %m")));
556 }
557 }
558
559 while (true)
560 {
561 ssize_t ret;
564
565 /*
566 * The client always sends first, so try to go ahead and read the
567 * length and wait on the socket to be readable again if that fails.
568 */
569 ret = read_or_wait(port, sizeof(uint32));
570 if (ret < 0)
571 return ret;
572
573 /*
574 * Get the length for this packet from the length header.
575 */
576 input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
577
578 /* Done with the length, reset our buffer */
579 PqGSSRecvLength = 0;
580
581 /*
582 * During initialization, packets are always fully consumed and
583 * shouldn't ever be over PQ_GSS_AUTH_BUFFER_SIZE in total length.
584 *
585 * Verify on our side that the client doesn't do something funny.
586 */
587 if (input.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
588 {
590 (errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
591 (size_t) input.length,
592 PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))));
593 return -1;
594 }
595
596 /*
597 * Get the rest of the packet so we can pass it to GSSAPI to accept
598 * the context.
599 */
600 ret = read_or_wait(port, input.length);
601 if (ret < 0)
602 return ret;
603
604 input.value = PqGSSRecvBuffer;
605
606 /* Process incoming data. (The client sends first.) */
607 major = gss_accept_sec_context(&minor, &port->gss->ctx,
610 &port->gss->name, NULL, &output, NULL,
612
613 if (GSS_ERROR(major))
614 {
615 pg_GSS_error(_("could not accept GSSAPI security context"),
616 major, minor);
618 return -1;
619 }
620 else if (!(major & GSS_S_CONTINUE_NEEDED))
621 {
622 /*
623 * rfc2744 technically permits context negotiation to be complete
624 * both with and without a packet to be sent.
625 */
626 complete_next = true;
627 }
628
630 {
632 port->gss->delegated_creds = true;
633 }
634
635 /* Done handling the incoming packet, reset our buffer */
636 PqGSSRecvLength = 0;
637
638 /*
639 * Check if we have data to send and, if we do, make sure to send it
640 * all
641 */
642 if (output.length > 0)
643 {
644 uint32 netlen = pg_hton32(output.length);
645
646 if (output.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))
647 {
649 (errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
650 (size_t) output.length,
651 PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32))));
653 return -1;
654 }
655
657 PqGSSSendLength += sizeof(uint32);
658
660 PqGSSSendLength += output.length;
661
662 /* we don't bother with PqGSSSendConsumed here */
663
665 {
668
669 /*
670 * If we got back an error and it wasn't just
671 * EWOULDBLOCK/EAGAIN/EINTR, then give up.
672 */
673 if (ret < 0 &&
674 !(errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
675 {
677 return -1;
678 }
679
680 /* Wait and retry if we couldn't write yet */
681 if (ret <= 0)
682 {
686 continue;
687 }
688
689 PqGSSSendNext += ret;
690 }
691
692 /* Done sending the packet, reset our buffer */
694
696 }
697
698 /*
699 * If we got back that the connection is finished being set up, now
700 * that we've sent the last packet, exit our loop.
701 */
702 if (complete_next)
703 break;
704 }
705
706 /*
707 * Release the large authentication buffers and allocate the ones we want
708 * for normal operation.
709 */
719 errmsg("out of memory")));
722
723 /*
724 * Determine the max packet size which will fit in our buffer, after
725 * accounting for the length. be_gssapi_write will need this.
726 */
730
731 if (GSS_ERROR(major))
732 {
733 pg_GSS_error(_("GSSAPI size check error"), major, minor);
734 return -1;
735 }
736
737 port->gss->enc = true;
738
739 return 0;
740}
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:874
#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 84 of file be-secure-gssapi.c.

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSRecvBuffer

char* PqGSSRecvBuffer
static

Definition at line 76 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 77 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 79 of file be-secure-gssapi.c.

Referenced by be_gssapi_read(), and secure_open_gssapi().

◆ PqGSSResultLength

int PqGSSResultLength
static

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

Referenced by be_gssapi_read(), and secure_open_gssapi().

◆ PqGSSResultNext

int PqGSSResultNext
static

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

Referenced by be_gssapi_read(), and secure_open_gssapi().

◆ PqGSSSendBuffer

char* PqGSSSendBuffer
static

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

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSSendConsumed

int PqGSSSendConsumed
static

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

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSSendLength

int PqGSSSendLength
static

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

Referenced by be_gssapi_write(), and secure_open_gssapi().

◆ PqGSSSendNext

int PqGSSSendNext
static

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

Referenced by be_gssapi_write(), and secure_open_gssapi().