PostgreSQL Source Code  git master
fe-secure-gssapi.c File Reference
#include "postgres_fe.h"
#include "fe-gssapi-common.h"
#include "libpq-fe.h"
#include "libpq-int.h"
#include "port/pg_bswap.h"
Include dependency graph for fe-secure-gssapi.c:

Go to the source code of this file.

Macros

#define GSS_REQUIRED_FLAGS
 
#define PQ_GSS_SEND_BUFFER_SIZE   16384
 
#define PQ_GSS_RECV_BUFFER_SIZE   16384
 
#define PqGSSSendBuffer   (conn->gss_SendBuffer)
 
#define PqGSSSendLength   (conn->gss_SendLength)
 
#define PqGSSSendNext   (conn->gss_SendNext)
 
#define PqGSSSendConsumed   (conn->gss_SendConsumed)
 
#define PqGSSRecvBuffer   (conn->gss_RecvBuffer)
 
#define PqGSSRecvLength   (conn->gss_RecvLength)
 
#define PqGSSResultBuffer   (conn->gss_ResultBuffer)
 
#define PqGSSResultLength   (conn->gss_ResultLength)
 
#define PqGSSResultNext   (conn->gss_ResultNext)
 
#define PqGSSMaxPktSize   (conn->gss_MaxPktSize)
 

Functions

ssize_t pg_GSS_write (PGconn *conn, const void *ptr, size_t len)
 
ssize_t pg_GSS_read (PGconn *conn, void *ptr, size_t len)
 
static PostgresPollingStatusType gss_read (PGconn *conn, void *recv_buffer, size_t length, ssize_t *ret)
 
PostgresPollingStatusType pqsecure_open_gss (PGconn *conn)
 
void * PQgetgssctx (PGconn *conn)
 
int PQgssEncInUse (PGconn *conn)
 

Macro Definition Documentation

◆ GSS_REQUIRED_FLAGS

#define GSS_REQUIRED_FLAGS
Value:
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \
GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG

Definition at line 26 of file fe-secure-gssapi.c.

◆ PQ_GSS_RECV_BUFFER_SIZE

#define PQ_GSS_RECV_BUFFER_SIZE   16384

Definition at line 54 of file fe-secure-gssapi.c.

◆ PQ_GSS_SEND_BUFFER_SIZE

#define PQ_GSS_SEND_BUFFER_SIZE   16384

Definition at line 53 of file fe-secure-gssapi.c.

◆ PqGSSMaxPktSize

#define PqGSSMaxPktSize   (conn->gss_MaxPktSize)

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

◆ PqGSSRecvBuffer

#define PqGSSRecvBuffer   (conn->gss_RecvBuffer)

Definition at line 65 of file fe-secure-gssapi.c.

◆ PqGSSRecvLength

#define PqGSSRecvLength   (conn->gss_RecvLength)

Definition at line 66 of file fe-secure-gssapi.c.

◆ PqGSSResultBuffer

#define PqGSSResultBuffer   (conn->gss_ResultBuffer)

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

◆ PqGSSResultLength

#define PqGSSResultLength   (conn->gss_ResultLength)

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

◆ PqGSSResultNext

#define PqGSSResultNext   (conn->gss_ResultNext)

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

◆ PqGSSSendBuffer

#define PqGSSSendBuffer   (conn->gss_SendBuffer)

Definition at line 61 of file fe-secure-gssapi.c.

◆ PqGSSSendConsumed

#define PqGSSSendConsumed   (conn->gss_SendConsumed)

Definition at line 64 of file fe-secure-gssapi.c.

◆ PqGSSSendLength

#define PqGSSSendLength   (conn->gss_SendLength)

Definition at line 62 of file fe-secure-gssapi.c.

◆ PqGSSSendNext

#define PqGSSSendNext   (conn->gss_SendNext)

Definition at line 63 of file fe-secure-gssapi.c.

Function Documentation

◆ gss_read()

static PostgresPollingStatusType gss_read ( PGconn conn,
void *  recv_buffer,
size_t  length,
ssize_t *  ret 
)
static

Definition at line 432 of file fe-secure-gssapi.c.

433 {
434  *ret = pqsecure_raw_read(conn, recv_buffer, length);
435  if (*ret < 0)
436  {
437  if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
438  return PGRES_POLLING_READING;
439  else
440  return PGRES_POLLING_FAILED;
441  }
442 
443  /* Check for EOF */
444  if (*ret == 0)
445  {
446  int result = pqReadReady(conn);
447 
448  if (result < 0)
449  return PGRES_POLLING_FAILED;
450 
451  if (!result)
452  return PGRES_POLLING_READING;
453 
454  *ret = pqsecure_raw_read(conn, recv_buffer, length);
455  if (*ret < 0)
456  {
457  if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
458  return PGRES_POLLING_READING;
459  else
460  return PGRES_POLLING_FAILED;
461  }
462  if (*ret == 0)
463  return PGRES_POLLING_FAILED;
464  }
465 
466  return PGRES_POLLING_OK;
467 }
int pqReadReady(PGconn *conn)
Definition: fe-misc.c:1015
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:230
@ PGRES_POLLING_OK
Definition: libpq-fe.h:89
@ PGRES_POLLING_READING
Definition: libpq-fe.h:87
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:86
PGconn * conn
Definition: streamutil.c:54
#define EINTR
Definition: win32_port.h:369
#define EWOULDBLOCK
Definition: win32_port.h:375
#define EAGAIN
Definition: win32_port.h:367

References conn, EAGAIN, EINTR, EWOULDBLOCK, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, pqReadReady(), and pqsecure_raw_read().

Referenced by pqsecure_open_gss().

◆ pg_GSS_read()

ssize_t pg_GSS_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 263 of file fe-secure-gssapi.c.

264 {
265  OM_uint32 major,
266  minor;
267  gss_buffer_desc input = GSS_C_EMPTY_BUFFER,
268  output = GSS_C_EMPTY_BUFFER;
269  ssize_t ret;
270  size_t bytes_returned = 0;
271  gss_ctx_id_t gctx = conn->gctx;
272 
273  /*
274  * The plan here is to read one incoming encrypted packet into
275  * PqGSSRecvBuffer, decrypt it into PqGSSResultBuffer, and then dole out
276  * data from there to the caller. When we exhaust the current input
277  * packet, read another.
278  */
279  while (bytes_returned < len)
280  {
281  int conf_state = 0;
282 
283  /* Check if we have data in our buffer that we can return immediately */
285  {
286  size_t bytes_in_buffer = PqGSSResultLength - PqGSSResultNext;
287  size_t bytes_to_copy = Min(bytes_in_buffer, len - bytes_returned);
288 
289  /*
290  * Copy the data from our result buffer into the caller's buffer,
291  * at the point where we last left off filling their buffer.
292  */
293  memcpy((char *) ptr + bytes_returned, PqGSSResultBuffer + PqGSSResultNext, bytes_to_copy);
294  PqGSSResultNext += bytes_to_copy;
295  bytes_returned += bytes_to_copy;
296 
297  /*
298  * At this point, we've either filled the caller's buffer or
299  * emptied our result buffer. Either way, return to caller. In
300  * the second case, we could try to read another encrypted packet,
301  * but the odds are good that there isn't one available. (If this
302  * isn't true, we chose too small a max packet size.) In any
303  * case, there's no harm letting the caller process the data we've
304  * already returned.
305  */
306  break;
307  }
308 
309  /* Result buffer is empty, so reset buffer pointers */
311 
312  /*
313  * Because we chose above to return immediately as soon as we emit
314  * some data, bytes_returned must be zero at this point. Therefore
315  * the failure exits below can just return -1 without worrying about
316  * whether we already emitted some data.
317  */
318  Assert(bytes_returned == 0);
319 
320  /*
321  * At this point, our result buffer is empty with more bytes being
322  * requested to be read. We are now ready to load the next packet and
323  * decrypt it (entirely) into our result buffer.
324  */
325 
326  /* Collect the length if we haven't already */
327  if (PqGSSRecvLength < sizeof(uint32))
328  {
330  sizeof(uint32) - PqGSSRecvLength);
331 
332  /* If ret <= 0, pqsecure_raw_read already set the correct errno */
333  if (ret <= 0)
334  return ret;
335 
336  PqGSSRecvLength += ret;
337 
338  /* If we still haven't got the length, return to the caller */
339  if (PqGSSRecvLength < sizeof(uint32))
340  {
341  errno = EWOULDBLOCK;
342  return -1;
343  }
344  }
345 
346  /* Decode the packet length and check for overlength packet */
347  input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
348 
349  if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
350  {
351  libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)",
352  (size_t) input.length,
353  PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));
354  errno = EIO; /* for lack of a better idea */
355  return -1;
356  }
357 
358  /*
359  * Read as much of the packet as we are able to on this call into
360  * wherever we left off from the last time we were called.
361  */
363  input.length - (PqGSSRecvLength - sizeof(uint32)));
364  /* If ret <= 0, pqsecure_raw_read already set the correct errno */
365  if (ret <= 0)
366  return ret;
367 
368  PqGSSRecvLength += ret;
369 
370  /* If we don't yet have the whole packet, return to the caller */
371  if (PqGSSRecvLength - sizeof(uint32) < input.length)
372  {
373  errno = EWOULDBLOCK;
374  return -1;
375  }
376 
377  /*
378  * We now have the full packet and we can perform the decryption and
379  * refill our result buffer, then loop back up to pass data back to
380  * the caller. Note that error exits below here must take care of
381  * releasing the gss output buffer.
382  */
383  output.value = NULL;
384  output.length = 0;
385  input.value = PqGSSRecvBuffer + sizeof(uint32);
386 
387  major = gss_unwrap(&minor, gctx, &input, &output, &conf_state, NULL);
388  if (major != GSS_S_COMPLETE)
389  {
390  pg_GSS_error(libpq_gettext("GSSAPI unwrap error"), conn,
391  major, minor);
392  ret = -1;
393  errno = EIO; /* for lack of a better idea */
394  goto cleanup;
395  }
396 
397  if (conf_state == 0)
398  {
399  libpq_append_conn_error(conn, "incoming GSSAPI message did not use confidentiality");
400  ret = -1;
401  errno = EIO; /* for lack of a better idea */
402  goto cleanup;
403  }
404 
405  memcpy(PqGSSResultBuffer, output.value, output.length);
406  PqGSSResultLength = output.length;
407 
408  /* Our receive buffer is now empty, reset it */
409  PqGSSRecvLength = 0;
410 
411  /* Release buffer storage allocated by GSSAPI */
412  gss_release_buffer(&minor, &output);
413  }
414 
415  ret = bytes_returned;
416 
417 cleanup:
418  /* Release GSSAPI buffer storage, if we didn't already */
419  if (output.value != NULL)
420  gss_release_buffer(&minor, &output);
421  return ret;
422 }
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
static void cleanup(void)
Definition: bootstrap.c:696
unsigned int uint32
Definition: c.h:442
#define Min(x, y)
Definition: c.h:937
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1312
#define PqGSSResultNext
#define PqGSSResultLength
#define PqGSSRecvBuffer
#define PQ_GSS_RECV_BUFFER_SIZE
#define PqGSSRecvLength
#define PqGSSResultBuffer
#define libpq_gettext(x)
Definition: libpq-int.h:882
Assert(fmt[strlen(fmt) - 1] !='\n')
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
const void size_t len
static void output(uint64 loop_count)

References Assert(), cleanup(), conn, EWOULDBLOCK, len, libpq_append_conn_error(), libpq_gettext, Min, output(), pg_GSS_error(), pg_ntoh32, PQ_GSS_RECV_BUFFER_SIZE, PqGSSRecvBuffer, PqGSSRecvLength, PqGSSResultBuffer, PqGSSResultLength, PqGSSResultNext, and pqsecure_raw_read().

Referenced by pqsecure_read().

◆ pg_GSS_write()

ssize_t pg_GSS_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 86 of file fe-secure-gssapi.c.

87 {
88  OM_uint32 major,
89  minor;
90  gss_buffer_desc input,
91  output = GSS_C_EMPTY_BUFFER;
92  ssize_t ret = -1;
93  size_t bytes_sent = 0;
94  size_t bytes_to_encrypt;
95  size_t bytes_encrypted;
96  gss_ctx_id_t gctx = conn->gctx;
97 
98  /*
99  * When we get a failure, we must not tell the caller we have successfully
100  * transmitted everything, else it won't retry. Hence a "success"
101  * (positive) return value must only count source bytes corresponding to
102  * fully-transmitted encrypted packets. The amount of source data
103  * corresponding to the current partly-transmitted packet is remembered in
104  * PqGSSSendConsumed. On a retry, the caller *must* be sending that data
105  * again, so if it offers a len less than that, something is wrong.
106  */
107  if (len < PqGSSSendConsumed)
108  {
110  "GSSAPI caller failed to retransmit all data needing to be retried\n");
111  errno = EINVAL;
112  return -1;
113  }
114 
115  /* Discount whatever source data we already encrypted. */
116  bytes_to_encrypt = len - PqGSSSendConsumed;
117  bytes_encrypted = PqGSSSendConsumed;
118 
119  /*
120  * Loop through encrypting data and sending it out until it's all done or
121  * pqsecure_raw_write() complains (which would likely mean that the socket
122  * is non-blocking and the requested send() would block, or there was some
123  * kind of actual error).
124  */
125  while (bytes_to_encrypt || PqGSSSendLength)
126  {
127  int conf_state = 0;
128  uint32 netlen;
129 
130  /*
131  * Check if we have data in the encrypted output buffer that needs to
132  * be sent (possibly left over from a previous call), and if so, try
133  * to send it. If we aren't able to, return that fact back up to the
134  * caller.
135  */
136  if (PqGSSSendLength)
137  {
138  ssize_t retval;
139  ssize_t amount = PqGSSSendLength - PqGSSSendNext;
140 
142  if (retval <= 0)
143  {
144  /*
145  * Report any previously-sent data; if there was none, reflect
146  * the pqsecure_raw_write result up to our caller. When there
147  * was some, we're effectively assuming that any interesting
148  * failure condition will recur on the next try.
149  */
150  if (bytes_sent)
151  return bytes_sent;
152  return retval;
153  }
154 
155  /*
156  * Check if this was a partial write, and if so, move forward that
157  * far in our buffer and try again.
158  */
159  if (retval != amount)
160  {
161  PqGSSSendNext += retval;
162  continue;
163  }
164 
165  /* We've successfully sent whatever data was in that packet. */
166  bytes_sent += PqGSSSendConsumed;
167 
168  /* All encrypted data was sent, our buffer is empty now. */
170  }
171 
172  /*
173  * Check if there are any bytes left to encrypt. If not, we're done.
174  */
175  if (!bytes_to_encrypt)
176  break;
177 
178  /*
179  * Check how much we are being asked to send, if it's too much, then
180  * we will have to loop and possibly be called multiple times to get
181  * through all the data.
182  */
183  if (bytes_to_encrypt > PqGSSMaxPktSize)
184  input.length = PqGSSMaxPktSize;
185  else
186  input.length = bytes_to_encrypt;
187 
188  input.value = (char *) ptr + bytes_encrypted;
189 
190  output.value = NULL;
191  output.length = 0;
192 
193  /*
194  * Create the next encrypted packet. Any failure here is considered a
195  * hard failure, so we return -1 even if bytes_sent > 0.
196  */
197  major = gss_wrap(&minor, gctx, 1, GSS_C_QOP_DEFAULT,
198  &input, &conf_state, &output);
199  if (major != GSS_S_COMPLETE)
200  {
201  pg_GSS_error(libpq_gettext("GSSAPI wrap error"), conn, major, minor);
202  errno = EIO; /* for lack of a better idea */
203  goto cleanup;
204  }
205 
206  if (conf_state == 0)
207  {
208  libpq_append_conn_error(conn, "outgoing GSSAPI message would not use confidentiality");
209  errno = EIO; /* for lack of a better idea */
210  goto cleanup;
211  }
212 
213  if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
214  {
215  libpq_append_conn_error(conn, "client tried to send oversize GSSAPI packet (%zu > %zu)",
216  (size_t) output.length,
217  PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32));
218  errno = EIO; /* for lack of a better idea */
219  goto cleanup;
220  }
221 
222  bytes_encrypted += input.length;
223  bytes_to_encrypt -= input.length;
224  PqGSSSendConsumed += input.length;
225 
226  /* 4 network-order bytes of length, then payload */
227  netlen = pg_hton32(output.length);
228  memcpy(PqGSSSendBuffer + PqGSSSendLength, &netlen, sizeof(uint32));
229  PqGSSSendLength += sizeof(uint32);
230 
231  memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length);
232  PqGSSSendLength += output.length;
233 
234  /* Release buffer storage allocated by GSSAPI */
235  gss_release_buffer(&minor, &output);
236  }
237 
238  /* If we get here, our counters should all match up. */
239  Assert(bytes_sent == len);
240  Assert(bytes_sent == bytes_encrypted);
241 
242  ret = bytes_sent;
243 
244 cleanup:
245  /* Release GSSAPI buffer storage, if we didn't already */
246  if (output.value != NULL)
247  gss_release_buffer(&minor, &output);
248  return ret;
249 }
#define PqGSSSendLength
#define PqGSSSendConsumed
#define PqGSSSendBuffer
#define PQ_GSS_SEND_BUFFER_SIZE
#define PqGSSMaxPktSize
#define PqGSSSendNext
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition: fe-secure.c:346
#define pg_hton32(x)
Definition: pg_bswap.h:121
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
PQExpBufferData errorMessage
Definition: libpq-int.h:588

References appendPQExpBufferStr(), Assert(), cleanup(), conn, pg_conn::errorMessage, len, libpq_append_conn_error(), libpq_gettext, output(), pg_GSS_error(), pg_hton32, PQ_GSS_SEND_BUFFER_SIZE, PqGSSMaxPktSize, PqGSSSendBuffer, PqGSSSendConsumed, PqGSSSendLength, PqGSSSendNext, and pqsecure_raw_write().

Referenced by pqsecure_write().

◆ PQgetgssctx()

void* PQgetgssctx ( PGconn conn)

Definition at line 707 of file fe-secure-gssapi.c.

708 {
709  if (!conn)
710  return NULL;
711 
712  return conn->gctx;
713 }

References conn.

◆ PQgssEncInUse()

int PQgssEncInUse ( PGconn conn)

Definition at line 719 of file fe-secure-gssapi.c.

720 {
721  if (!conn || !conn->gctx)
722  return 0;
723 
724  return conn->gssenc;
725 }

References conn.

Referenced by printGSSInfo().

◆ pqsecure_open_gss()

PostgresPollingStatusType pqsecure_open_gss ( PGconn conn)

Definition at line 476 of file fe-secure-gssapi.c.

477 {
478  ssize_t ret;
479  OM_uint32 major,
480  minor;
481  uint32 netlen;
483  gss_buffer_desc input = GSS_C_EMPTY_BUFFER,
484  output = GSS_C_EMPTY_BUFFER;
485 
486  /*
487  * If first time through for this connection, allocate buffers and
488  * initialize state variables. By malloc'ing the buffers separately, we
489  * ensure that they are sufficiently aligned for the length-word accesses
490  * that we do in some places in this file.
491  */
492  if (PqGSSSendBuffer == NULL)
493  {
498  {
499  libpq_append_conn_error(conn, "out of memory");
500  return PGRES_POLLING_FAILED;
501  }
504  }
505 
506  /*
507  * Check if we have anything to send from a prior call and if so, send it.
508  */
509  if (PqGSSSendLength)
510  {
511  ssize_t amount = PqGSSSendLength - PqGSSSendNext;
512 
514  if (ret < 0)
515  {
516  if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
517  return PGRES_POLLING_WRITING;
518  else
519  return PGRES_POLLING_FAILED;
520  }
521 
522  if (ret < amount)
523  {
524  PqGSSSendNext += ret;
525  return PGRES_POLLING_WRITING;
526  }
527 
529  }
530 
531  /*
532  * Client sends first, and sending creates a context, therefore this will
533  * be false the first time through, and then when we get called again we
534  * will check for incoming data.
535  */
536  if (conn->gctx)
537  {
538  /* Process any incoming data we might have */
539 
540  /* See if we are still trying to get the length */
541  if (PqGSSRecvLength < sizeof(uint32))
542  {
543  /* Attempt to get the length first */
544  result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, sizeof(uint32) - PqGSSRecvLength, &ret);
545  if (result != PGRES_POLLING_OK)
546  return result;
547 
548  PqGSSRecvLength += ret;
549 
550  if (PqGSSRecvLength < sizeof(uint32))
551  return PGRES_POLLING_READING;
552  }
553 
554  /*
555  * Check if we got an error packet
556  *
557  * This is safe to do because we shouldn't ever get a packet over 8192
558  * and therefore the actual length bytes, being that they are in
559  * network byte order, for any real packet will start with two zero
560  * bytes.
561  */
562  if (PqGSSRecvBuffer[0] == 'E')
563  {
564  /*
565  * For an error packet during startup, we don't get a length, so
566  * simply read as much as we can fit into our buffer (as a string,
567  * so leave a spot at the end for a NULL byte too) and report that
568  * back to the caller.
569  */
571  if (result != PGRES_POLLING_OK)
572  return result;
573 
574  PqGSSRecvLength += ret;
575 
577 
578  return PGRES_POLLING_FAILED;
579  }
580 
581  /*
582  * We should have the whole length at this point, so pull it out and
583  * then read whatever we have left of the packet
584  */
585 
586  /* Get the length and check for over-length packet */
587  input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
588  if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
589  {
590  libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)",
591  (size_t) input.length,
592  PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));
593  return PGRES_POLLING_FAILED;
594  }
595 
596  /*
597  * Read as much of the packet as we are able to on this call into
598  * wherever we left off from the last time we were called.
599  */
601  input.length - (PqGSSRecvLength - sizeof(uint32)), &ret);
602  if (result != PGRES_POLLING_OK)
603  return result;
604 
605  PqGSSRecvLength += ret;
606 
607  /*
608  * If we got less than the rest of the packet then we need to return
609  * and be called again.
610  */
611  if (PqGSSRecvLength - sizeof(uint32) < input.length)
612  return PGRES_POLLING_READING;
613 
614  input.value = PqGSSRecvBuffer + sizeof(uint32);
615  }
616 
617  /* Load the service name (no-op if already done */
619  if (ret != STATUS_OK)
620  return PGRES_POLLING_FAILED;
621 
622  /*
623  * Call GSS init context, either with an empty input, or with a complete
624  * packet from the server.
625  */
626  major = gss_init_sec_context(&minor, conn->gcred, &conn->gctx,
627  conn->gtarg_nam, GSS_C_NO_OID,
628  GSS_REQUIRED_FLAGS, 0, 0, &input, NULL,
629  &output, NULL, NULL);
630 
631  /* GSS Init Sec Context uses the whole packet, so clear it */
632  PqGSSRecvLength = 0;
633 
634  if (GSS_ERROR(major))
635  {
636  pg_GSS_error(libpq_gettext("could not initiate GSSAPI security context"),
637  conn, major, minor);
638  return PGRES_POLLING_FAILED;
639  }
640 
641  if (output.length == 0)
642  {
643  /*
644  * We're done - hooray! Set flag to tell the low-level I/O routines
645  * to do GSS wrapping/unwrapping.
646  */
647  conn->gssenc = true;
648 
649  /* Clean up */
650  gss_release_cred(&minor, &conn->gcred);
651  conn->gcred = GSS_C_NO_CREDENTIAL;
652  gss_release_buffer(&minor, &output);
653 
654  /*
655  * Determine the max packet size which will fit in our buffer, after
656  * accounting for the length. pg_GSS_write will need this.
657  */
658  major = gss_wrap_size_limit(&minor, conn->gctx, 1, GSS_C_QOP_DEFAULT,
660  &PqGSSMaxPktSize);
661 
662  if (GSS_ERROR(major))
663  {
664  pg_GSS_error(libpq_gettext("GSSAPI size check error"), conn,
665  major, minor);
666  return PGRES_POLLING_FAILED;
667  }
668 
669  return PGRES_POLLING_OK;
670  }
671 
672  /* Must have output.length > 0 */
673  if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
674  {
675  pg_GSS_error(libpq_gettext("GSSAPI context establishment error"),
676  conn, major, minor);
677  gss_release_buffer(&minor, &output);
678  return PGRES_POLLING_FAILED;
679  }
680 
681  /* Queue the token for writing */
682  netlen = pg_hton32(output.length);
683 
684  memcpy(PqGSSSendBuffer, (char *) &netlen, sizeof(uint32));
685  PqGSSSendLength += sizeof(uint32);
686 
687  memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length);
688  PqGSSSendLength += output.length;
689 
690  /* We don't bother with PqGSSSendConsumed here */
691 
692  /* Release buffer storage allocated by GSSAPI */
693  gss_release_buffer(&minor, &output);
694 
695  /* Ask to be called again to write data */
696  return PGRES_POLLING_WRITING;
697 }
#define STATUS_OK
Definition: c.h:1108
int pg_GSS_load_servicename(PGconn *conn)
#define GSS_REQUIRED_FLAGS
static PostgresPollingStatusType gss_read(PGconn *conn, void *recv_buffer, size_t length, ssize_t *ret)
#define malloc(a)
Definition: header.h:50
PostgresPollingStatusType
Definition: libpq-fe.h:85
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:88
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265

References appendPQExpBuffer(), conn, EAGAIN, EINTR, pg_conn::errorMessage, EWOULDBLOCK, gss_read(), GSS_REQUIRED_FLAGS, libpq_append_conn_error(), libpq_gettext, malloc, output(), pg_GSS_error(), pg_GSS_load_servicename(), pg_hton32, pg_ntoh32, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQ_GSS_RECV_BUFFER_SIZE, PQ_GSS_SEND_BUFFER_SIZE, PqGSSMaxPktSize, PqGSSRecvBuffer, PqGSSRecvLength, PqGSSResultBuffer, PqGSSResultLength, PqGSSResultNext, PqGSSSendBuffer, PqGSSSendConsumed, PqGSSSendLength, PqGSSSendNext, pqsecure_raw_write(), and STATUS_OK.

Referenced by PQconnectPoll().