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-2019, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/libpq/be-secure-gssapi.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres.h"
16 
17 #include <unistd.h>
18 
19 #include "libpq/auth.h"
20 #include "libpq/be-gssapi-common.h"
21 #include "libpq/libpq.h"
22 #include "libpq/pqformat.h"
23 #include "miscadmin.h"
24 #include "pgstat.h"
25 
26 
27 /*
28  * Handle the encryption/decryption of data using GSSAPI.
29  *
30  * In the encrypted data stream on the wire, we break up the data
31  * into packets where each packet starts with a sizeof(uint32)-byte
32  * length (not allowed to be larger than the buffer sizes defined
33  * below) and then the encrypted data of that length immediately
34  * following.
35  *
36  * Encrypted data typically ends up being larger than the same data
37  * unencrypted, so we use fixed-size buffers for handling the
38  * encryption/decryption which are larger than PQComm's buffer will
39  * typically be to minimize the times where we have to make multiple
40  * packets and therefore sets of recv/send calls for a single
41  * read/write call to us.
42  *
43  * NOTE: The client and server have to agree on the max packet size,
44  * because we have to pass an entire packet to GSSAPI at a time and we
45  * don't want the other side to send arbitrairly huge packets as we
46  * would have to allocate memory for them to then pass them to GSSAPI.
47  */
48 #define PQ_GSS_SEND_BUFFER_SIZE 16384
49 #define PQ_GSS_RECV_BUFFER_SIZE 16384
50 
51 /* PqGSSSendBuffer is for *encrypted* data */
53 static int PqGSSSendPointer; /* Next index to store a byte in
54  * PqGSSSendBuffer */
55 static int PqGSSSendStart; /* Next index to send a byte in
56  * PqGSSSendBuffer */
57 
58 /* PqGSSRecvBuffer is for *encrypted* data */
60 static int PqGSSRecvLength; /* End of data available in PqGSSRecvBuffer */
61 
62 /* PqGSSResultBuffer is for *unencrypted* data */
64 static int PqGSSResultPointer; /* Next index to read a byte from
65  * PqGSSResultBuffer */
66 static int PqGSSResultLength; /* End of data available in PqGSSResultBuffer */
67 
68 uint32 max_packet_size; /* Maximum size we can encrypt and fit the
69  * results into our output buffer */
70 
71 /*
72  * Attempt to write len bytes of data from ptr along a GSSAPI-encrypted connection.
73  *
74  * Connection must be fully established (including authentication step) before
75  * calling. Returns the bytes actually consumed once complete. Data is
76  * internally buffered; in the case of an incomplete write, the amount of data we
77  * processed (encrypted into our output buffer to be sent) will be returned. If
78  * an error occurs or we would block, a negative value is returned and errno is
79  * set appropriately.
80  *
81  * To continue writing in the case of EWOULDBLOCK and similar, call this function
82  * again with matching ptr and len parameters.
83  */
84 ssize_t
85 be_gssapi_write(Port *port, void *ptr, size_t len)
86 {
87  size_t bytes_to_encrypt = len;
88  size_t bytes_encrypted = 0;
89 
90  /*
91  * Loop through encrypting data and sending it out until
92  * secure_raw_write() complains (which would likely mean that the socket
93  * is non-blocking and the requested send() would block, or there was some
94  * kind of actual error) and then return.
95  */
96  while (bytes_to_encrypt || PqGSSSendPointer)
97  {
98  OM_uint32 major,
99  minor;
100  gss_buffer_desc input,
101  output;
102  int conf = 0;
103  uint32 netlen;
104  pg_gssinfo *gss = port->gss;
105 
106  /*
107  * Check if we have data in the encrypted output buffer that needs to
108  * be sent, and if so, try to send it. If we aren't able to, return
109  * that back up to the caller.
110  */
111  if (PqGSSSendPointer)
112  {
113  ssize_t ret;
114  ssize_t amount = PqGSSSendPointer - PqGSSSendStart;
115 
116  ret = secure_raw_write(port, PqGSSSendBuffer + PqGSSSendStart, amount);
117  if (ret <= 0)
118  {
119  /*
120  * If we encrypted some data and it's in our output buffer,
121  * but send() is saying that we would block, then tell the
122  * caller how far we got with encrypting the data so that they
123  * can call us again with whatever is left, at which point we
124  * will try to send the remaining encrypted data first and
125  * then move on to encrypting the rest of the data.
126  */
127  if (bytes_encrypted != 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR))
128  return bytes_encrypted;
129  else
130  return ret;
131  }
132 
133  /*
134  * Check if this was a partial write, and if so, move forward that
135  * far in our buffer and try again.
136  */
137  if (ret != amount)
138  {
139  PqGSSSendStart += ret;
140  continue;
141  }
142 
143  /* All encrypted data was sent, our buffer is empty now. */
144  PqGSSSendPointer = PqGSSSendStart = 0;
145  }
146 
147  /*
148  * Check if there are any bytes left to encrypt. If not, we're done.
149  */
150  if (!bytes_to_encrypt)
151  return bytes_encrypted;
152 
153  /*
154  * max_packet_size is the maximum amount of unencrypted data that,
155  * when encrypted, will fit into our encrypted-data output buffer.
156  *
157  * If we are being asked to send more than max_packet_size unencrypted
158  * data, then we will loop and create multiple packets, each with
159  * max_packet_size unencrypted data encrypted in them (at least, until
160  * secure_raw_write returns a failure saying we would be blocked, at
161  * which point we will let the caller know how far we got).
162  */
163  if (bytes_to_encrypt > max_packet_size)
164  input.length = max_packet_size;
165  else
166  input.length = bytes_to_encrypt;
167 
168  input.value = (char *) ptr + bytes_encrypted;
169 
170  output.value = NULL;
171  output.length = 0;
172 
173  /* Create the next encrypted packet */
174  major = gss_wrap(&minor, gss->ctx, 1, GSS_C_QOP_DEFAULT,
175  &input, &conf, &output);
176  if (major != GSS_S_COMPLETE)
177  pg_GSS_error(FATAL, gettext_noop("GSSAPI wrap error"), major, minor);
178 
179  if (conf == 0)
180  ereport(FATAL,
181  (errmsg("GSSAPI did not provide confidentiality")));
182 
183  if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
184  ereport(FATAL,
185  (errmsg("server tried to send oversize GSSAPI packet: %zu bytes",
186  (size_t) output.length)));
187 
188  bytes_encrypted += input.length;
189  bytes_to_encrypt -= input.length;
190 
191  /* 4 network-order length bytes, then payload */
192  netlen = htonl(output.length);
193  memcpy(PqGSSSendBuffer + PqGSSSendPointer, &netlen, sizeof(uint32));
194  PqGSSSendPointer += sizeof(uint32);
195 
196  memcpy(PqGSSSendBuffer + PqGSSSendPointer, output.value, output.length);
197  PqGSSSendPointer += output.length;
198  }
199 
200  return bytes_encrypted;
201 }
202 
203 /*
204  * Read up to len bytes from a GSSAPI-encrypted connection into ptr. Call
205  * only after the connection has been fully established (i.e., GSSAPI
206  * authentication is complete). On success, returns the number of bytes
207  * written into ptr; otherwise, returns -1 and sets errno appropriately.
208  */
209 ssize_t
210 be_gssapi_read(Port *port, void *ptr, size_t len)
211 {
212  OM_uint32 major,
213  minor;
214  gss_buffer_desc input,
215  output;
216  ssize_t ret;
217  size_t bytes_to_return = len;
218  size_t bytes_returned = 0;
219  int conf = 0;
220  pg_gssinfo *gss = port->gss;
221 
222  /*
223  * The goal here is to read an incoming encrypted packet, one at a time,
224  * decrypt it into our out buffer, returning to the caller what they asked
225  * for, and then saving anything else for the next call.
226  *
227  * First we look to see if we have unencrypted bytes available and, if so,
228  * copy those to the result. If the caller asked for more than we had
229  * immediately available, then we try to read a packet off the wire and
230  * decrypt it. If the read would block, then return the amount of
231  * unencrypted data we copied into the caller's ptr.
232  */
233  while (bytes_to_return)
234  {
235  /* Check if we have data in our buffer that we can return immediately */
237  {
238  int bytes_in_buffer = PqGSSResultLength - PqGSSResultPointer;
239  int bytes_to_copy = bytes_in_buffer < len - bytes_returned ? bytes_in_buffer : len - bytes_returned;
240 
241  /*
242  * Copy the data from our output buffer into the caller's buffer,
243  * at the point where we last left off filling their buffer
244  */
245  memcpy((char *) ptr + bytes_returned, PqGSSResultBuffer + PqGSSResultPointer, bytes_to_copy);
246  PqGSSResultPointer += bytes_to_copy;
247  bytes_to_return -= bytes_to_copy;
248  bytes_returned += bytes_to_copy;
249 
250  /* Check if our result buffer is now empty and, if so, reset */
251  if (PqGSSResultPointer == PqGSSResultLength)
252  PqGSSResultPointer = PqGSSResultLength = 0;
253 
254  continue;
255  }
256 
257  /*
258  * At this point, our output buffer should be empty with more bytes
259  * being requested to be read. We are now ready to load the next
260  * packet and decrypt it (entirely) into our buffer.
261  *
262  * If we get a partial read back while trying to read a packet off the
263  * wire then we return the number of unencrypted bytes we were able to
264  * copy (if any, if we didn't copy any, then we return whatever
265  * secure_raw_read returned when we called it; likely -1) into the
266  * caller's ptr and wait to be called again, until we get a full
267  * packet to decrypt.
268  */
269 
270  /* Check if we have the size of the packet already in our buffer. */
271  if (PqGSSRecvLength < sizeof(uint32))
272  {
273  /*
274  * We were not able to get the length of the packet last time, so
275  * we need to do that first.
276  */
278  sizeof(uint32) - PqGSSRecvLength);
279  if (ret < 0)
280  return bytes_returned ? bytes_returned : ret;
281 
282  PqGSSRecvLength += ret;
283 
284  /*
285  * If we only got part of the packet length, then return however
286  * many unencrypted bytes we copied to the caller and wait to be
287  * called again.
288  */
289  if (PqGSSRecvLength < sizeof(uint32))
290  return bytes_returned;
291  }
292 
293  /*
294  * We have the length of the next packet at this point, so pull it out
295  * and then read whatever we have left of the packet to read.
296  */
297  input.length = ntohl(*(uint32 *) PqGSSRecvBuffer);
298 
299  /* Check for over-length packet */
300  if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
301  ereport(FATAL,
302  (errmsg("oversize GSSAPI packet sent by the client: %zu bytes",
303  (size_t) input.length)));
304 
305  /*
306  * Read as much of the packet as we are able to on this call into
307  * wherever we left off from the last time we were called.
308  */
309  ret = secure_raw_read(port, PqGSSRecvBuffer + PqGSSRecvLength,
310  input.length - (PqGSSRecvLength - sizeof(uint32)));
311  if (ret < 0)
312  return bytes_returned ? bytes_returned : ret;
313 
314  PqGSSRecvLength += ret;
315 
316  /*
317  * If we got less than the rest of the packet then we need to return
318  * and be called again. If we didn't have any bytes to return on this
319  * run then return -1 and set errno to EWOULDBLOCK.
320  */
321  if (PqGSSRecvLength - sizeof(uint32) < input.length)
322  {
323  if (!bytes_returned)
324  {
325  errno = EWOULDBLOCK;
326  return -1;
327  }
328 
329  return bytes_returned;
330  }
331 
332  /*
333  * We now have the full packet and we can perform the decryption and
334  * refill our output buffer, then loop back up to pass that back to
335  * the user.
336  */
337  output.value = NULL;
338  output.length = 0;
339  input.value = PqGSSRecvBuffer + sizeof(uint32);
340 
341  major = gss_unwrap(&minor, gss->ctx, &input, &output, &conf, NULL);
342  if (major != GSS_S_COMPLETE)
343  pg_GSS_error(FATAL, gettext_noop("GSSAPI unwrap error"),
344  major, minor);
345 
346  if (conf == 0)
347  ereport(FATAL,
348  (errmsg("GSSAPI did not provide confidentiality")));
349 
350  memcpy(PqGSSResultBuffer, output.value, output.length);
351 
352  PqGSSResultLength = output.length;
353 
354  /* Our buffer is now empty, reset it */
355  PqGSSRecvLength = 0;
356 
357  gss_release_buffer(&minor, &output);
358  }
359 
360  return bytes_returned;
361 }
362 
363 /*
364  * Read the specified number of bytes off the wire, waiting using
365  * WaitLatchOrSocket if we would block.
366  *
367  * Results are read into PqGSSRecvBuffer.
368  *
369  * Will always return either -1, to indicate a permanent error, or len.
370  */
371 static ssize_t
372 read_or_wait(Port *port, ssize_t len)
373 {
374  ssize_t ret;
375 
376  /*
377  * Keep going until we either read in everything we were asked to, or we
378  * error out.
379  */
380  while (PqGSSRecvLength != len)
381  {
383 
384  /*
385  * If we got back an error and it wasn't just EWOULDBLOCK/EAGAIN, then
386  * give up.
387  */
388  if (ret < 0 && !(errno == EWOULDBLOCK || errno == EAGAIN))
389  return -1;
390 
391  /*
392  * Ok, we got back either a positive value, zero, or a negative result
393  * but EWOULDBLOCK or EAGAIN was set.
394  *
395  * If it was zero or negative, then we try to wait on the socket to be
396  * readable again.
397  */
398  if (ret <= 0)
399  {
400  /*
401  * If we got back less than zero, indicating an error, and that
402  * wasn't just a EWOULDBLOCK/EAGAIN, then give up.
403  */
404  if (ret < 0 && !(errno == EWOULDBLOCK || errno == EAGAIN))
405  return -1;
406 
407  /*
408  * We got back either zero, or -1 with EWOULDBLOCK/EAGAIN, so wait
409  * on socket to be readable again.
410  */
413  port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER);
414 
415  /*
416  * If we got back zero bytes, and then waited on the socket to be
417  * readable and got back zero bytes on a second read, then this is
418  * EOF and the client hung up on us.
419  *
420  * If we did get data here, then we can just fall through and
421  * handle it just as if we got data the first time.
422  *
423  * Otherwise loop back to the top and try again.
424  */
425  if (ret == 0)
426  {
428  if (ret == 0)
429  return -1;
430  }
431  else
432  continue;
433  }
434 
435  PqGSSRecvLength += ret;
436  }
437 
438  return len;
439 }
440 
441 /*
442  * Start up a GSSAPI-encrypted connection. This performs GSSAPI
443  * authentication; after this function completes, it is safe to call
444  * be_gssapi_read and be_gssapi_write. Returns -1 and logs on failure;
445  * otherwise, returns 0 and marks the connection as ready for GSSAPI
446  * encryption.
447  *
448  * Note that unlike the be_gssapi_read/be_gssapi_write functions, this
449  * function WILL block on the socket to be ready for read/write (using
450  * WaitLatchOrSocket) as appropriate while establishing the GSSAPI
451  * session.
452  */
453 ssize_t
455 {
456  bool complete_next = false;
457  OM_uint32 major,
458  minor;
459 
460  /* initialize state variables */
462 
463  /*
464  * Use the configured keytab, if there is one. Unfortunately, Heimdal
465  * doesn't support the cred store extensions, so use the env var.
466  */
467  if (pg_krb_server_keyfile != NULL && strlen(pg_krb_server_keyfile) > 0)
468  setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1);
469 
470  while (true)
471  {
472  ssize_t ret;
473  gss_buffer_desc input,
474  output = GSS_C_EMPTY_BUFFER;
475 
476  /*
477  * The client always sends first, so try to go ahead and read the
478  * length and wait on the socket to be readable again if that fails.
479  */
480  ret = read_or_wait(port, sizeof(uint32));
481  if (ret < 0)
482  return ret;
483 
484  /*
485  * Get the length for this packet from the length header.
486  */
487  input.length = ntohl(*(uint32 *) PqGSSRecvBuffer);
488 
489  /* Done with the length, reset our buffer */
490  PqGSSRecvLength = 0;
491 
492  /*
493  * During initialization, packets are always fully consumed and
494  * shouldn't ever be over PQ_GSS_RECV_BUFFER_SIZE in length.
495  *
496  * Verify on our side that the client doesn't do something funny.
497  */
498  if (input.length > PQ_GSS_RECV_BUFFER_SIZE)
499  ereport(FATAL,
500  (errmsg("oversize GSSAPI packet sent by the client: %zu bytes",
501  (size_t) input.length)));
502 
503  /*
504  * Get the rest of the packet so we can pass it to GSSAPI to accept
505  * the context.
506  */
507  ret = read_or_wait(port, input.length);
508  if (ret < 0)
509  return ret;
510 
511  input.value = PqGSSRecvBuffer;
512 
513  /* Process incoming data. (The client sends first.) */
514  major = gss_accept_sec_context(&minor, &port->gss->ctx,
515  GSS_C_NO_CREDENTIAL, &input,
516  GSS_C_NO_CHANNEL_BINDINGS,
517  &port->gss->name, NULL, &output, NULL,
518  NULL, NULL);
519  if (GSS_ERROR(major))
520  {
521  pg_GSS_error(ERROR, gettext_noop("GSSAPI context error"),
522  major, minor);
523  gss_release_buffer(&minor, &output);
524  return -1;
525  }
526  else if (!(major & GSS_S_CONTINUE_NEEDED))
527  {
528  /*
529  * rfc2744 technically permits context negotiation to be complete
530  * both with and without a packet to be sent.
531  */
532  complete_next = true;
533  }
534 
535  /* Done handling the incoming packet, reset our buffer */
536  PqGSSRecvLength = 0;
537 
538  /*
539  * Check if we have data to send and, if we do, make sure to send it
540  * all
541  */
542  if (output.length != 0)
543  {
544  uint32 netlen = htonl(output.length);
545 
546  if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
547  ereport(FATAL,
548  (errmsg("server tried to send oversize GSSAPI packet: %zu bytes",
549  (size_t) output.length)));
550 
551  memcpy(PqGSSSendBuffer, (char *) &netlen, sizeof(uint32));
552  PqGSSSendPointer += sizeof(uint32);
553 
554  memcpy(PqGSSSendBuffer + PqGSSSendPointer, output.value, output.length);
555  PqGSSSendPointer += output.length;
556 
557  while (PqGSSSendStart != sizeof(uint32) + output.length)
558  {
559  ret = secure_raw_write(port, PqGSSSendBuffer + PqGSSSendStart, sizeof(uint32) + output.length - PqGSSSendStart);
560  if (ret <= 0)
561  {
564  port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER);
565  continue;
566  }
567 
568  PqGSSSendStart += ret;
569  }
570 
571  /* Done sending the packet, reset our buffer */
573 
574  gss_release_buffer(&minor, &output);
575  }
576 
577  /*
578  * If we got back that the connection is finished being set up, now
579  * that's we've sent the last packet, exit our loop.
580  */
581  if (complete_next)
582  break;
583  }
584 
585  /*
586  * Determine the max packet size which will fit in our buffer, after
587  * accounting for the length
588  */
589  major = gss_wrap_size_limit(&minor, port->gss->ctx, 1, GSS_C_QOP_DEFAULT,
591 
592  if (GSS_ERROR(major))
593  pg_GSS_error(FATAL, gettext_noop("GSSAPI size check error"),
594  major, minor);
595 
596  port->gss->enc = true;
597 
598  return 0;
599 }
600 
601 /*
602  * Return if GSSAPI authentication was used on this connection.
603  */
604 bool
606 {
607  if (!port || !port->gss)
608  return false;
609 
610  return port->gss->auth;
611 }
612 
613 /*
614  * Return if GSSAPI encryption is enabled and being used on this connection.
615  */
616 bool
618 {
619  if (!port || !port->gss)
620  return false;
621 
622  return port->gss->enc;
623 }
624 
625 /*
626  * Return the GSSAPI principal used for authentication on this connection.
627  */
628 const char *
630 {
631  if (!port || !port->gss->auth)
632  return NULL;
633 
634  return port->gss->princ;
635 }
#define WL_SOCKET_WRITEABLE
Definition: latch.h:126
static char PqGSSRecvBuffer[PQ_GSS_RECV_BUFFER_SIZE]
const char * be_gssapi_get_princ(Port *port)
static int PqGSSResultPointer
static int PqGSSSendPointer
#define EAGAIN
Definition: win32_port.h:330
static void output(uint64 loop_count)
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition: be-secure.c:331
#define gettext_noop(x)
Definition: c.h:1117
Definition: libpq-be.h:120
static char PqGSSSendBuffer[PQ_GSS_SEND_BUFFER_SIZE]
#define WL_SOCKET_READABLE
Definition: latch.h:125
pgsocket sock
Definition: libpq-be.h:122
static int PqGSSRecvLength
uint32 max_packet_size
#define PQ_GSS_RECV_BUFFER_SIZE
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition: latch.c:369
unsigned int uint32
Definition: c.h:358
#define ereport(elevel, rest)
Definition: elog.h:141
static int port
Definition: pg_regress.c:92
static int PqGSSResultLength
bool be_gssapi_get_enc(Port *port)
ssize_t be_gssapi_write(Port *port, void *ptr, size_t len)
ssize_t secure_open_gssapi(Port *port)
ssize_t secure_raw_read(Port *port, void *ptr, size_t len)
Definition: be-secure.c:235
static ssize_t read_or_wait(Port *port, ssize_t len)
#define PQ_GSS_SEND_BUFFER_SIZE
char * pg_krb_server_keyfile
Definition: auth.c:166
void * gss
Definition: libpq-be.h:184
int errmsg(const char *fmt,...)
Definition: elog.c:784
static int PqGSSSendStart
static char PqGSSResultBuffer[PQ_GSS_RECV_BUFFER_SIZE]
struct Latch * MyLatch
Definition: globals.c:54
#define EWOULDBLOCK
Definition: win32_port.h:338
#define EINTR
Definition: win32_port.h:332
void pg_GSS_error(int severity, const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
bool be_gssapi_get_auth(Port *port)
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:129
ssize_t be_gssapi_read(Port *port, void *ptr, size_t len)