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_state = 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_state, &output);
176  if (major != GSS_S_COMPLETE)
177  pg_GSS_error(FATAL, gettext_noop("GSSAPI wrap error"), major, minor);
178 
179  if (conf_state == 0)
180  ereport(FATAL,
181  (errmsg("outgoing GSSAPI message would not use 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 > %zu)",
186  (size_t) output.length,
187  PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))));
188 
189  bytes_encrypted += input.length;
190  bytes_to_encrypt -= input.length;
191 
192  /* 4 network-order length bytes, then payload */
193  netlen = htonl(output.length);
194  memcpy(PqGSSSendBuffer + PqGSSSendPointer, &netlen, sizeof(uint32));
195  PqGSSSendPointer += sizeof(uint32);
196 
197  memcpy(PqGSSSendBuffer + PqGSSSendPointer, output.value, output.length);
198  PqGSSSendPointer += output.length;
199  }
200 
201  return bytes_encrypted;
202 }
203 
204 /*
205  * Read up to len bytes from a GSSAPI-encrypted connection into ptr. Call
206  * only after the connection has been fully established (i.e., GSSAPI
207  * authentication is complete). On success, returns the number of bytes
208  * written into ptr; otherwise, returns -1 and sets errno appropriately.
209  */
210 ssize_t
211 be_gssapi_read(Port *port, void *ptr, size_t len)
212 {
213  OM_uint32 major,
214  minor;
215  gss_buffer_desc input,
216  output;
217  ssize_t ret;
218  size_t bytes_to_return = len;
219  size_t bytes_returned = 0;
220  int conf_state = 0;
221  pg_gssinfo *gss = port->gss;
222 
223  /*
224  * The goal here is to read an incoming encrypted packet, one at a time,
225  * decrypt it into our out buffer, returning to the caller what they asked
226  * for, and then saving anything else for the next call.
227  *
228  * First we look to see if we have unencrypted bytes available and, if so,
229  * copy those to the result. If the caller asked for more than we had
230  * immediately available, then we try to read a packet off the wire and
231  * decrypt it. If the read would block, then return the amount of
232  * unencrypted data we copied into the caller's ptr.
233  */
234  while (bytes_to_return)
235  {
236  /* Check if we have data in our buffer that we can return immediately */
238  {
239  int bytes_in_buffer = PqGSSResultLength - PqGSSResultPointer;
240  int bytes_to_copy = bytes_in_buffer < len - bytes_returned ? bytes_in_buffer : len - bytes_returned;
241 
242  /*
243  * Copy the data from our output buffer into the caller's buffer,
244  * at the point where we last left off filling their buffer
245  */
246  memcpy((char *) ptr + bytes_returned, PqGSSResultBuffer + PqGSSResultPointer, bytes_to_copy);
247  PqGSSResultPointer += bytes_to_copy;
248  bytes_to_return -= bytes_to_copy;
249  bytes_returned += bytes_to_copy;
250 
251  /* Check if our result buffer is now empty and, if so, reset */
252  if (PqGSSResultPointer == PqGSSResultLength)
253  PqGSSResultPointer = PqGSSResultLength = 0;
254 
255  continue;
256  }
257 
258  /*
259  * At this point, our output buffer should be empty with more bytes
260  * being requested to be read. We are now ready to load the next
261  * packet and decrypt it (entirely) into our buffer.
262  *
263  * If we get a partial read back while trying to read a packet off the
264  * wire then we return the number of unencrypted bytes we were able to
265  * copy (if any, if we didn't copy any, then we return whatever
266  * secure_raw_read returned when we called it; likely -1) into the
267  * caller's ptr and wait to be called again, until we get a full
268  * packet to decrypt.
269  */
270 
271  /* Check if we have the size of the packet already in our buffer. */
272  if (PqGSSRecvLength < sizeof(uint32))
273  {
274  /*
275  * We were not able to get the length of the packet last time, so
276  * we need to do that first.
277  */
279  sizeof(uint32) - PqGSSRecvLength);
280  if (ret < 0)
281  return bytes_returned ? bytes_returned : ret;
282 
283  PqGSSRecvLength += ret;
284 
285  /*
286  * If we only got part of the packet length, then return however
287  * many unencrypted bytes we copied to the caller and wait to be
288  * called again.
289  */
290  if (PqGSSRecvLength < sizeof(uint32))
291  return bytes_returned;
292  }
293 
294  /*
295  * We have the length of the next packet at this point, so pull it out
296  * and then read whatever we have left of the packet to read.
297  */
298  input.length = ntohl(*(uint32 *) PqGSSRecvBuffer);
299 
300  /* Check for over-length packet */
301  if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
302  ereport(FATAL,
303  (errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)",
304  (size_t) input.length,
305  PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))));
306 
307  /*
308  * Read as much of the packet as we are able to on this call into
309  * wherever we left off from the last time we were called.
310  */
311  ret = secure_raw_read(port, PqGSSRecvBuffer + PqGSSRecvLength,
312  input.length - (PqGSSRecvLength - sizeof(uint32)));
313  if (ret < 0)
314  return bytes_returned ? bytes_returned : ret;
315 
316  PqGSSRecvLength += ret;
317 
318  /*
319  * If we got less than the rest of the packet then we need to return
320  * and be called again. If we didn't have any bytes to return on this
321  * run then return -1 and set errno to EWOULDBLOCK.
322  */
323  if (PqGSSRecvLength - sizeof(uint32) < input.length)
324  {
325  if (!bytes_returned)
326  {
327  errno = EWOULDBLOCK;
328  return -1;
329  }
330 
331  return bytes_returned;
332  }
333 
334  /*
335  * We now have the full packet and we can perform the decryption and
336  * refill our output buffer, then loop back up to pass that back to
337  * the user.
338  */
339  output.value = NULL;
340  output.length = 0;
341  input.value = PqGSSRecvBuffer + sizeof(uint32);
342 
343  major = gss_unwrap(&minor, gss->ctx, &input, &output, &conf_state, NULL);
344  if (major != GSS_S_COMPLETE)
345  pg_GSS_error(FATAL, gettext_noop("GSSAPI unwrap error"),
346  major, minor);
347 
348  if (conf_state == 0)
349  ereport(FATAL,
350  (errmsg("incoming GSSAPI message did not use confidentiality")));
351 
352  memcpy(PqGSSResultBuffer, output.value, output.length);
353 
354  PqGSSResultLength = output.length;
355 
356  /* Our buffer is now empty, reset it */
357  PqGSSRecvLength = 0;
358 
359  gss_release_buffer(&minor, &output);
360  }
361 
362  return bytes_returned;
363 }
364 
365 /*
366  * Read the specified number of bytes off the wire, waiting using
367  * WaitLatchOrSocket if we would block.
368  *
369  * Results are read into PqGSSRecvBuffer.
370  *
371  * Will always return either -1, to indicate a permanent error, or len.
372  */
373 static ssize_t
374 read_or_wait(Port *port, ssize_t len)
375 {
376  ssize_t ret;
377 
378  /*
379  * Keep going until we either read in everything we were asked to, or we
380  * error out.
381  */
382  while (PqGSSRecvLength != len)
383  {
385 
386  /*
387  * If we got back an error and it wasn't just EWOULDBLOCK/EAGAIN, then
388  * give up.
389  */
390  if (ret < 0 && !(errno == EWOULDBLOCK || errno == EAGAIN))
391  return -1;
392 
393  /*
394  * Ok, we got back either a positive value, zero, or a negative result
395  * but EWOULDBLOCK or EAGAIN was set.
396  *
397  * If it was zero or negative, then we try to wait on the socket to be
398  * readable again.
399  */
400  if (ret <= 0)
401  {
402  /*
403  * If we got back less than zero, indicating an error, and that
404  * wasn't just a EWOULDBLOCK/EAGAIN, then give up.
405  */
406  if (ret < 0 && !(errno == EWOULDBLOCK || errno == EAGAIN))
407  return -1;
408 
409  /*
410  * We got back either zero, or -1 with EWOULDBLOCK/EAGAIN, so wait
411  * on socket to be readable again.
412  */
415  port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER);
416 
417  /*
418  * If we got back zero bytes, and then waited on the socket to be
419  * readable and got back zero bytes on a second read, then this is
420  * EOF and the client hung up on us.
421  *
422  * If we did get data here, then we can just fall through and
423  * handle it just as if we got data the first time.
424  *
425  * Otherwise loop back to the top and try again.
426  */
427  if (ret == 0)
428  {
430  if (ret == 0)
431  return -1;
432  }
433  else
434  continue;
435  }
436 
437  PqGSSRecvLength += ret;
438  }
439 
440  return len;
441 }
442 
443 /*
444  * Start up a GSSAPI-encrypted connection. This performs GSSAPI
445  * authentication; after this function completes, it is safe to call
446  * be_gssapi_read and be_gssapi_write. Returns -1 and logs on failure;
447  * otherwise, returns 0 and marks the connection as ready for GSSAPI
448  * encryption.
449  *
450  * Note that unlike the be_gssapi_read/be_gssapi_write functions, this
451  * function WILL block on the socket to be ready for read/write (using
452  * WaitLatchOrSocket) as appropriate while establishing the GSSAPI
453  * session.
454  */
455 ssize_t
457 {
458  bool complete_next = false;
459  OM_uint32 major,
460  minor;
461 
462  /* initialize state variables */
464 
465  /*
466  * Use the configured keytab, if there is one. Unfortunately, Heimdal
467  * doesn't support the cred store extensions, so use the env var.
468  */
469  if (pg_krb_server_keyfile != NULL && strlen(pg_krb_server_keyfile) > 0)
470  setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1);
471 
472  while (true)
473  {
474  ssize_t ret;
475  gss_buffer_desc input,
476  output = GSS_C_EMPTY_BUFFER;
477 
478  /*
479  * The client always sends first, so try to go ahead and read the
480  * length and wait on the socket to be readable again if that fails.
481  */
482  ret = read_or_wait(port, sizeof(uint32));
483  if (ret < 0)
484  return ret;
485 
486  /*
487  * Get the length for this packet from the length header.
488  */
489  input.length = ntohl(*(uint32 *) PqGSSRecvBuffer);
490 
491  /* Done with the length, reset our buffer */
492  PqGSSRecvLength = 0;
493 
494  /*
495  * During initialization, packets are always fully consumed and
496  * shouldn't ever be over PQ_GSS_RECV_BUFFER_SIZE in length.
497  *
498  * Verify on our side that the client doesn't do something funny.
499  */
500  if (input.length > PQ_GSS_RECV_BUFFER_SIZE)
501  ereport(FATAL,
502  (errmsg("oversize GSSAPI packet sent by the client (%zu > %d)",
503  (size_t) input.length,
505 
506  /*
507  * Get the rest of the packet so we can pass it to GSSAPI to accept
508  * the context.
509  */
510  ret = read_or_wait(port, input.length);
511  if (ret < 0)
512  return ret;
513 
514  input.value = PqGSSRecvBuffer;
515 
516  /* Process incoming data. (The client sends first.) */
517  major = gss_accept_sec_context(&minor, &port->gss->ctx,
518  GSS_C_NO_CREDENTIAL, &input,
519  GSS_C_NO_CHANNEL_BINDINGS,
520  &port->gss->name, NULL, &output, NULL,
521  NULL, NULL);
522  if (GSS_ERROR(major))
523  {
524  pg_GSS_error(ERROR, gettext_noop("could not accept GSSAPI security context"),
525  major, minor);
526  gss_release_buffer(&minor, &output);
527  return -1;
528  }
529  else if (!(major & GSS_S_CONTINUE_NEEDED))
530  {
531  /*
532  * rfc2744 technically permits context negotiation to be complete
533  * both with and without a packet to be sent.
534  */
535  complete_next = true;
536  }
537 
538  /* Done handling the incoming packet, reset our buffer */
539  PqGSSRecvLength = 0;
540 
541  /*
542  * Check if we have data to send and, if we do, make sure to send it
543  * all
544  */
545  if (output.length != 0)
546  {
547  uint32 netlen = htonl(output.length);
548 
549  if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
550  ereport(FATAL,
551  (errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)",
552  (size_t) output.length,
553  PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))));
554 
555  memcpy(PqGSSSendBuffer, (char *) &netlen, sizeof(uint32));
556  PqGSSSendPointer += sizeof(uint32);
557 
558  memcpy(PqGSSSendBuffer + PqGSSSendPointer, output.value, output.length);
559  PqGSSSendPointer += output.length;
560 
561  while (PqGSSSendStart != sizeof(uint32) + output.length)
562  {
563  ret = secure_raw_write(port, PqGSSSendBuffer + PqGSSSendStart, sizeof(uint32) + output.length - PqGSSSendStart);
564  if (ret <= 0)
565  {
568  port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER);
569  continue;
570  }
571 
572  PqGSSSendStart += ret;
573  }
574 
575  /* Done sending the packet, reset our buffer */
577 
578  gss_release_buffer(&minor, &output);
579  }
580 
581  /*
582  * If we got back that the connection is finished being set up, now
583  * that's we've sent the last packet, exit our loop.
584  */
585  if (complete_next)
586  break;
587  }
588 
589  /*
590  * Determine the max packet size which will fit in our buffer, after
591  * accounting for the length
592  */
593  major = gss_wrap_size_limit(&minor, port->gss->ctx, 1, GSS_C_QOP_DEFAULT,
595 
596  if (GSS_ERROR(major))
597  pg_GSS_error(FATAL, gettext_noop("GSSAPI size check error"),
598  major, minor);
599 
600  port->gss->enc = true;
601 
602  return 0;
603 }
604 
605 /*
606  * Return if GSSAPI authentication was used on this connection.
607  */
608 bool
610 {
611  if (!port || !port->gss)
612  return false;
613 
614  return port->gss->auth;
615 }
616 
617 /*
618  * Return if GSSAPI encryption is enabled and being used on this connection.
619  */
620 bool
622 {
623  if (!port || !port->gss)
624  return false;
625 
626  return port->gss->enc;
627 }
628 
629 /*
630  * Return the GSSAPI principal used for authentication on this connection.
631  */
632 const char *
634 {
635  if (!port || !port->gss->auth)
636  return NULL;
637 
638  return port->gss->princ;
639 }
#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:321
static void output(uint64 loop_count)
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition: be-secure.c:330
#define gettext_noop(x)
Definition: c.h:1148
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:359
#define ereport(elevel, rest)
Definition: elog.h:141
static int port
Definition: pg_regress.c:91
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:234
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:171
void * gss
Definition: libpq-be.h:184
int errmsg(const char *fmt,...)
Definition: elog.c:822
static int PqGSSSendStart
static char PqGSSResultBuffer[PQ_GSS_RECV_BUFFER_SIZE]
struct Latch * MyLatch
Definition: globals.c:54
#define EWOULDBLOCK
Definition: win32_port.h:329
#define EINTR
Definition: win32_port.h:323
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)