PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
fe-auth.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * fe-auth.c
4  * The front-end (client) authorization routines
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * src/interfaces/libpq/fe-auth.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 /*
16  * INTERFACE ROUTINES
17  * frontend (client) routines:
18  * pg_fe_sendauth send authentication information
19  * pg_fe_getauthname get user's name according to the client side
20  * of the authentication system
21  */
22 
23 #include "postgres_fe.h"
24 
25 #ifdef WIN32
26 #include "win32.h"
27 #else
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
31 #include <sys/socket.h>
32 #ifdef HAVE_SYS_UCRED_H
33 #include <sys/ucred.h>
34 #endif
35 #ifndef MAXHOSTNAMELEN
36 #include <netdb.h> /* for MAXHOSTNAMELEN on some */
37 #endif
38 #include <pwd.h>
39 #endif
40 
41 #include "common/md5.h"
42 #include "libpq-fe.h"
43 #include "libpq/scram.h"
44 #include "fe-auth.h"
45 
46 
47 #ifdef ENABLE_GSS
48 /*
49  * GSSAPI authentication system.
50  */
51 
52 #if defined(WIN32) && !defined(_MSC_VER)
53 /*
54  * MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
55  * that contain the OIDs required. Redefine here, values copied
56  * from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
57  */
58 static const gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_desc =
59 {10, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"};
60 static GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE = &GSS_C_NT_HOSTBASED_SERVICE_desc;
61 #endif
62 
63 /*
64  * Fetch all errors of a specific type and append to "str".
65  */
66 static void
67 pg_GSS_error_int(PQExpBuffer str, const char *mprefix,
68  OM_uint32 stat, int type)
69 {
70  OM_uint32 lmin_s;
71  gss_buffer_desc lmsg;
72  OM_uint32 msg_ctx = 0;
73 
74  do
75  {
76  gss_display_status(&lmin_s, stat, type,
77  GSS_C_NO_OID, &msg_ctx, &lmsg);
78  appendPQExpBuffer(str, "%s: %s\n", mprefix, (char *) lmsg.value);
79  gss_release_buffer(&lmin_s, &lmsg);
80  } while (msg_ctx);
81 }
82 
83 /*
84  * GSSAPI errors contain two parts; put both into conn->errorMessage.
85  */
86 static void
87 pg_GSS_error(const char *mprefix, PGconn *conn,
88  OM_uint32 maj_stat, OM_uint32 min_stat)
89 {
91 
92  /* Fetch major error codes */
93  pg_GSS_error_int(&conn->errorMessage, mprefix, maj_stat, GSS_C_GSS_CODE);
94 
95  /* Add the minor codes as well */
96  pg_GSS_error_int(&conn->errorMessage, mprefix, min_stat, GSS_C_MECH_CODE);
97 }
98 
99 /*
100  * Continue GSS authentication with next token as needed.
101  */
102 static int
103 pg_GSS_continue(PGconn *conn, int payloadlen)
104 {
105  OM_uint32 maj_stat,
106  min_stat,
107  lmin_s;
108  gss_buffer_desc ginbuf;
109  gss_buffer_desc goutbuf;
110 
111  /*
112  * On first call, there's no input token. On subsequent calls, read the
113  * input token into a GSS buffer.
114  */
115  if (conn->gctx != GSS_C_NO_CONTEXT)
116  {
117  ginbuf.length = payloadlen;
118  ginbuf.value = malloc(payloadlen);
119  if (!ginbuf.value)
120  {
122  libpq_gettext("out of memory allocating GSSAPI buffer (%d)\n"),
123  payloadlen);
124  return STATUS_ERROR;
125  }
126  if (pqGetnchar(ginbuf.value, payloadlen, conn))
127  {
128  /*
129  * Shouldn't happen, because the caller should've ensured that the
130  * whole message is already in the input buffer.
131  */
132  free(ginbuf.value);
133  return STATUS_ERROR;
134  }
135  }
136 
137  maj_stat = gss_init_sec_context(&min_stat,
138  GSS_C_NO_CREDENTIAL,
139  &conn->gctx,
140  conn->gtarg_nam,
141  GSS_C_NO_OID,
142  GSS_C_MUTUAL_FLAG,
143  0,
144  GSS_C_NO_CHANNEL_BINDINGS,
145  (conn->gctx == GSS_C_NO_CONTEXT) ? GSS_C_NO_BUFFER : &ginbuf,
146  NULL,
147  &goutbuf,
148  NULL,
149  NULL);
150 
151  if (conn->gctx != GSS_C_NO_CONTEXT)
152  free(ginbuf.value);
153 
154  if (goutbuf.length != 0)
155  {
156  /*
157  * GSS generated data to send to the server. We don't care if it's the
158  * first or subsequent packet, just send the same kind of password
159  * packet.
160  */
161  if (pqPacketSend(conn, 'p',
162  goutbuf.value, goutbuf.length) != STATUS_OK)
163  {
164  gss_release_buffer(&lmin_s, &goutbuf);
165  return STATUS_ERROR;
166  }
167  }
168  gss_release_buffer(&lmin_s, &goutbuf);
169 
170  if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
171  {
172  pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
173  conn,
174  maj_stat, min_stat);
175  gss_release_name(&lmin_s, &conn->gtarg_nam);
176  if (conn->gctx)
177  gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
178  return STATUS_ERROR;
179  }
180 
181  if (maj_stat == GSS_S_COMPLETE)
182  gss_release_name(&lmin_s, &conn->gtarg_nam);
183 
184  return STATUS_OK;
185 }
186 
187 /*
188  * Send initial GSS authentication token
189  */
190 static int
191 pg_GSS_startup(PGconn *conn, int payloadlen)
192 {
193  OM_uint32 maj_stat,
194  min_stat;
195  int maxlen;
196  gss_buffer_desc temp_gbuf;
197  char *host = PQhost(conn);
198 
199  if (!(host && host[0] != '\0'))
200  {
202  libpq_gettext("host name must be specified\n"));
203  return STATUS_ERROR;
204  }
205 
206  if (conn->gctx)
207  {
209  libpq_gettext("duplicate GSS authentication request\n"));
210  return STATUS_ERROR;
211  }
212 
213  /*
214  * Import service principal name so the proper ticket can be acquired by
215  * the GSSAPI system.
216  */
217  maxlen = NI_MAXHOST + strlen(conn->krbsrvname) + 2;
218  temp_gbuf.value = (char *) malloc(maxlen);
219  if (!temp_gbuf.value)
220  {
222  libpq_gettext("out of memory\n"));
223  return STATUS_ERROR;
224  }
225  snprintf(temp_gbuf.value, maxlen, "%s@%s",
226  conn->krbsrvname, host);
227  temp_gbuf.length = strlen(temp_gbuf.value);
228 
229  maj_stat = gss_import_name(&min_stat, &temp_gbuf,
230  GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam);
231  free(temp_gbuf.value);
232 
233  if (maj_stat != GSS_S_COMPLETE)
234  {
235  pg_GSS_error(libpq_gettext("GSSAPI name import error"),
236  conn,
237  maj_stat, min_stat);
238  return STATUS_ERROR;
239  }
240 
241  /*
242  * Initial packet is the same as a continuation packet with no initial
243  * context.
244  */
245  conn->gctx = GSS_C_NO_CONTEXT;
246 
247  return pg_GSS_continue(conn, payloadlen);
248 }
249 #endif /* ENABLE_GSS */
250 
251 
252 #ifdef ENABLE_SSPI
253 /*
254  * SSPI authentication system (Windows only)
255  */
256 
257 static void
258 pg_SSPI_error(PGconn *conn, const char *mprefix, SECURITY_STATUS r)
259 {
260  char sysmsg[256];
261 
262  if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
263  FORMAT_MESSAGE_FROM_SYSTEM,
264  NULL, r, 0,
265  sysmsg, sizeof(sysmsg), NULL) == 0)
266  printfPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
267  mprefix, (unsigned int) r);
268  else
269  printfPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
270  mprefix, sysmsg, (unsigned int) r);
271 }
272 
273 /*
274  * Continue SSPI authentication with next token as needed.
275  */
276 static int
277 pg_SSPI_continue(PGconn *conn, int payloadlen)
278 {
279  SECURITY_STATUS r;
280  CtxtHandle newContext;
281  ULONG contextAttr;
282  SecBufferDesc inbuf;
283  SecBufferDesc outbuf;
284  SecBuffer OutBuffers[1];
285  SecBuffer InBuffers[1];
286  char *inputbuf = NULL;
287 
288  if (conn->sspictx != NULL)
289  {
290  /*
291  * On runs other than the first we have some data to send. Put this
292  * data in a SecBuffer type structure.
293  */
294  inputbuf = malloc(payloadlen);
295  if (!inputbuf)
296  {
298  libpq_gettext("out of memory allocating SSPI buffer (%d)\n"),
299  payloadlen);
300  return STATUS_ERROR;
301  }
302  if (pqGetnchar(inputbuf, payloadlen, conn))
303  {
304  /*
305  * Shouldn't happen, because the caller should've ensured that the
306  * whole message is already in the input buffer.
307  */
308  free(inputbuf);
309  return STATUS_ERROR;
310  }
311 
312  inbuf.ulVersion = SECBUFFER_VERSION;
313  inbuf.cBuffers = 1;
314  inbuf.pBuffers = InBuffers;
315  InBuffers[0].pvBuffer = inputbuf;
316  InBuffers[0].cbBuffer = payloadlen;
317  InBuffers[0].BufferType = SECBUFFER_TOKEN;
318  }
319 
320  OutBuffers[0].pvBuffer = NULL;
321  OutBuffers[0].BufferType = SECBUFFER_TOKEN;
322  OutBuffers[0].cbBuffer = 0;
323  outbuf.cBuffers = 1;
324  outbuf.pBuffers = OutBuffers;
325  outbuf.ulVersion = SECBUFFER_VERSION;
326 
327  r = InitializeSecurityContext(conn->sspicred,
328  conn->sspictx,
329  conn->sspitarget,
330  ISC_REQ_ALLOCATE_MEMORY,
331  0,
332  SECURITY_NETWORK_DREP,
333  (conn->sspictx == NULL) ? NULL : &inbuf,
334  0,
335  &newContext,
336  &outbuf,
337  &contextAttr,
338  NULL);
339 
340  /* we don't need the input anymore */
341  if (inputbuf)
342  free(inputbuf);
343 
344  if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
345  {
346  pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r);
347 
348  return STATUS_ERROR;
349  }
350 
351  if (conn->sspictx == NULL)
352  {
353  /* On first run, transfer retrieved context handle */
354  conn->sspictx = malloc(sizeof(CtxtHandle));
355  if (conn->sspictx == NULL)
356  {
357  printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
358  return STATUS_ERROR;
359  }
360  memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
361  }
362 
363  /*
364  * If SSPI returned any data to be sent to the server (as it normally
365  * would), send this data as a password packet.
366  */
367  if (outbuf.cBuffers > 0)
368  {
369  if (outbuf.cBuffers != 1)
370  {
371  /*
372  * This should never happen, at least not for Kerberos
373  * authentication. Keep check in case it shows up with other
374  * authentication methods later.
375  */
376  printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n");
377  return STATUS_ERROR;
378  }
379 
380  /*
381  * If the negotiation is complete, there may be zero bytes to send.
382  * The server is at this point not expecting any more data, so don't
383  * send it.
384  */
385  if (outbuf.pBuffers[0].cbBuffer > 0)
386  {
387  if (pqPacketSend(conn, 'p',
388  outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
389  {
390  FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
391  return STATUS_ERROR;
392  }
393  }
394  FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
395  }
396 
397  /* Cleanup is handled by the code in freePGconn() */
398  return STATUS_OK;
399 }
400 
401 /*
402  * Send initial SSPI authentication token.
403  * If use_negotiate is 0, use kerberos authentication package which is
404  * compatible with Unix. If use_negotiate is 1, use the negotiate package
405  * which supports both kerberos and NTLM, but is not compatible with Unix.
406  */
407 static int
408 pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen)
409 {
410  SECURITY_STATUS r;
411  TimeStamp expire;
412  char *host = PQhost(conn);
413 
414  conn->sspictx = NULL;
415 
416  /*
417  * Retrieve credentials handle
418  */
419  conn->sspicred = malloc(sizeof(CredHandle));
420  if (conn->sspicred == NULL)
421  {
422  printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
423  return STATUS_ERROR;
424  }
425 
426  r = AcquireCredentialsHandle(NULL,
427  use_negotiate ? "negotiate" : "kerberos",
428  SECPKG_CRED_OUTBOUND,
429  NULL,
430  NULL,
431  NULL,
432  NULL,
433  conn->sspicred,
434  &expire);
435  if (r != SEC_E_OK)
436  {
437  pg_SSPI_error(conn, libpq_gettext("could not acquire SSPI credentials"), r);
438  free(conn->sspicred);
439  conn->sspicred = NULL;
440  return STATUS_ERROR;
441  }
442 
443  /*
444  * Compute target principal name. SSPI has a different format from GSSAPI,
445  * but not more complex. We can skip the @REALM part, because Windows will
446  * fill that in for us automatically.
447  */
448  if (!(host && host[0] != '\0'))
449  {
451  libpq_gettext("host name must be specified\n"));
452  return STATUS_ERROR;
453  }
454  conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(host) + 2);
455  if (!conn->sspitarget)
456  {
457  printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
458  return STATUS_ERROR;
459  }
460  sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, host);
461 
462  /*
463  * Indicate that we're in SSPI authentication mode to make sure that
464  * pg_SSPI_continue is called next time in the negotiation.
465  */
466  conn->usesspi = 1;
467 
468  return pg_SSPI_continue(conn, payloadlen);
469 }
470 #endif /* ENABLE_SSPI */
471 
472 /*
473  * Initialize SASL authentication exchange.
474  */
475 static int
476 pg_SASL_init(PGconn *conn, int payloadlen)
477 {
478  char *initialresponse = NULL;
479  int initialresponselen;
480  bool done;
481  bool success;
482  const char *selected_mechanism;
483  PQExpBufferData mechanism_buf;
484 
485  initPQExpBuffer(&mechanism_buf);
486 
487  if (conn->sasl_state)
488  {
490  libpq_gettext("duplicate SASL authentication request\n"));
491  goto error;
492  }
493 
494  /*
495  * Parse the list of SASL authentication mechanisms in the
496  * AuthenticationSASL message, and select the best mechanism that we
497  * support. (Only SCRAM-SHA-256 is supported at the moment.)
498  */
499  selected_mechanism = NULL;
500  for (;;)
501  {
502  if (pqGets(&mechanism_buf, conn))
503  {
505  "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
506  goto error;
507  }
508  if (PQExpBufferDataBroken(mechanism_buf))
509  goto oom_error;
510 
511  /* An empty string indicates end of list */
512  if (mechanism_buf.data[0] == '\0')
513  break;
514 
515  /*
516  * If we have already selected a mechanism, just skip through the rest
517  * of the list.
518  */
519  if (selected_mechanism)
520  continue;
521 
522  /*
523  * Do we support this mechanism?
524  */
525  if (strcmp(mechanism_buf.data, SCRAM_SHA256_NAME) == 0)
526  {
527  char *password;
528 
529  conn->password_needed = true;
530  password = conn->connhost[conn->whichhost].password;
531  if (password == NULL)
532  password = conn->pgpass;
533  if (password == NULL || password[0] == '\0')
534  {
537  goto error;
538  }
539 
540  conn->sasl_state = pg_fe_scram_init(conn->pguser, password);
541  if (!conn->sasl_state)
542  goto oom_error;
543  selected_mechanism = SCRAM_SHA256_NAME;
544  }
545  }
546 
547  if (!selected_mechanism)
548  {
550  libpq_gettext("none of the server's SASL authentication mechanisms are supported\n"));
551  goto error;
552  }
553 
554  /* Get the mechanism-specific Initial Client Response, if any */
556  NULL, -1,
557  &initialresponse, &initialresponselen,
558  &done, &success, &conn->errorMessage);
559 
560  if (done && !success)
561  goto error;
562 
563  /*
564  * Build a SASLInitialResponse message, and send it.
565  */
566  if (pqPutMsgStart('p', true, conn))
567  goto error;
568  if (pqPuts(selected_mechanism, conn))
569  goto error;
570  if (initialresponse)
571  {
572  if (pqPutInt(initialresponselen, 4, conn))
573  goto error;
574  if (pqPutnchar(initialresponse, initialresponselen, conn))
575  goto error;
576  }
577  if (pqPutMsgEnd(conn))
578  goto error;
579  if (pqFlush(conn))
580  goto error;
581 
582  termPQExpBuffer(&mechanism_buf);
583  if (initialresponse)
584  free(initialresponse);
585 
586  return STATUS_OK;
587 
588 error:
589  termPQExpBuffer(&mechanism_buf);
590  if (initialresponse)
591  free(initialresponse);
592  return STATUS_ERROR;
593 
594 oom_error:
595  termPQExpBuffer(&mechanism_buf);
596  if (initialresponse)
597  free(initialresponse);
599  libpq_gettext("out of memory\n"));
600  return STATUS_ERROR;
601 }
602 
603 /*
604  * Exchange a message for SASL communication protocol with the backend.
605  * This should be used after calling pg_SASL_init to set up the status of
606  * the protocol.
607  */
608 static int
609 pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
610 {
611  char *output;
612  int outputlen;
613  bool done;
614  bool success;
615  int res;
616  char *challenge;
617 
618  /* Read the SASL challenge from the AuthenticationSASLContinue message. */
619  challenge = malloc(payloadlen + 1);
620  if (!challenge)
621  {
623  libpq_gettext("out of memory allocating SASL buffer (%d)\n"),
624  payloadlen);
625  return STATUS_ERROR;
626  }
627 
628  if (pqGetnchar(challenge, payloadlen, conn))
629  {
630  free(challenge);
631  return STATUS_ERROR;
632  }
633  /* For safety and convenience, ensure the buffer is NULL-terminated. */
634  challenge[payloadlen] = '\0';
635 
637  challenge, payloadlen,
638  &output, &outputlen,
639  &done, &success, &conn->errorMessage);
640  free(challenge); /* don't need the input anymore */
641 
642  if (final && !done)
643  {
644  if (outputlen != 0)
645  free(output);
646 
648  libpq_gettext("AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
649  return STATUS_ERROR;
650  }
651  if (outputlen != 0)
652  {
653  /*
654  * Send the SASL response to the server.
655  */
656  res = pqPacketSend(conn, 'p', output, outputlen);
657  free(output);
658 
659  if (res != STATUS_OK)
660  return STATUS_ERROR;
661  }
662 
663  if (done && !success)
664  return STATUS_ERROR;
665 
666  return STATUS_OK;
667 }
668 
669 /*
670  * Respond to AUTH_REQ_SCM_CREDS challenge.
671  *
672  * Note: this is dead code as of Postgres 9.1, because current backends will
673  * never send this challenge. But we must keep it as long as libpq needs to
674  * interoperate with pre-9.1 servers. It is believed to be needed only on
675  * Debian/kFreeBSD (ie, FreeBSD kernel with Linux userland, so that the
676  * getpeereid() function isn't provided by libc).
677  */
678 static int
680 {
681 #ifdef HAVE_STRUCT_CMSGCRED
682  char buf;
683  struct iovec iov;
684  struct msghdr msg;
685  struct cmsghdr *cmsg;
686  union
687  {
688  struct cmsghdr hdr;
689  unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))];
690  } cmsgbuf;
691 
692  /*
693  * The backend doesn't care what we send here, but it wants exactly one
694  * character to force recvmsg() to block and wait for us.
695  */
696  buf = '\0';
697  iov.iov_base = &buf;
698  iov.iov_len = 1;
699 
700  memset(&msg, 0, sizeof(msg));
701  msg.msg_iov = &iov;
702  msg.msg_iovlen = 1;
703 
704  /* We must set up a message that will be filled in by kernel */
705  memset(&cmsgbuf, 0, sizeof(cmsgbuf));
706  msg.msg_control = &cmsgbuf.buf;
707  msg.msg_controllen = sizeof(cmsgbuf.buf);
708  cmsg = CMSG_FIRSTHDR(&msg);
709  cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
710  cmsg->cmsg_level = SOL_SOCKET;
711  cmsg->cmsg_type = SCM_CREDS;
712 
713  if (sendmsg(conn->sock, &msg, 0) == -1)
714  {
715  char sebuf[256];
716 
718  "pg_local_sendauth: sendmsg: %s\n",
719  pqStrerror(errno, sebuf, sizeof(sebuf)));
720  return STATUS_ERROR;
721  }
722  return STATUS_OK;
723 #else
725  libpq_gettext("SCM_CRED authentication method not supported\n"));
726  return STATUS_ERROR;
727 #endif
728 }
729 
730 static int
732 {
733  int ret;
734  char *crypt_pwd = NULL;
735  const char *pwd_to_send;
736  char md5Salt[4];
737 
738  /* Read the salt from the AuthenticationMD5 message. */
739  if (areq == AUTH_REQ_MD5)
740  {
741  if (pqGetnchar(md5Salt, 4, conn))
742  return STATUS_ERROR; /* shouldn't happen */
743  }
744 
745  /* Encrypt the password if needed. */
746 
747  switch (areq)
748  {
749  case AUTH_REQ_MD5:
750  {
751  char *crypt_pwd2;
752 
753  /* Allocate enough space for two MD5 hashes */
754  crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
755  if (!crypt_pwd)
756  {
758  libpq_gettext("out of memory\n"));
759  return STATUS_ERROR;
760  }
761 
762  crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1;
763  if (!pg_md5_encrypt(password, conn->pguser,
764  strlen(conn->pguser), crypt_pwd2))
765  {
766  free(crypt_pwd);
767  return STATUS_ERROR;
768  }
769  if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), md5Salt,
770  4, crypt_pwd))
771  {
772  free(crypt_pwd);
773  return STATUS_ERROR;
774  }
775 
776  pwd_to_send = crypt_pwd;
777  break;
778  }
779  case AUTH_REQ_PASSWORD:
780  pwd_to_send = password;
781  break;
782  default:
783  return STATUS_ERROR;
784  }
785  /* Packet has a message type as of protocol 3.0 */
786  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
787  ret = pqPacketSend(conn, 'p', pwd_to_send, strlen(pwd_to_send) + 1);
788  else
789  ret = pqPacketSend(conn, 0, pwd_to_send, strlen(pwd_to_send) + 1);
790  if (crypt_pwd)
791  free(crypt_pwd);
792  return ret;
793 }
794 
795 /*
796  * pg_fe_sendauth
797  * client demux routine for processing an authentication request
798  *
799  * The server has sent us an authentication challenge (or OK). Send an
800  * appropriate response. The caller has ensured that the whole message is
801  * now in the input buffer, and has already read the type and length of
802  * it. We are responsible for reading any remaining extra data, specific
803  * to the authentication method. 'payloadlen' is the remaining length in
804  * the message.
805  */
806 int
807 pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
808 {
809  switch (areq)
810  {
811  case AUTH_REQ_OK:
812  break;
813 
814  case AUTH_REQ_KRB4:
816  libpq_gettext("Kerberos 4 authentication not supported\n"));
817  return STATUS_ERROR;
818 
819  case AUTH_REQ_KRB5:
821  libpq_gettext("Kerberos 5 authentication not supported\n"));
822  return STATUS_ERROR;
823 
824 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
825  case AUTH_REQ_GSS:
826 #if !defined(ENABLE_SSPI)
827  /* no native SSPI, so use GSSAPI library for it */
828  case AUTH_REQ_SSPI:
829 #endif
830  {
831  int r;
832 
833  pglock_thread();
834 
835  /*
836  * If we have both GSS and SSPI support compiled in, use SSPI
837  * support by default. This is overridable by a connection
838  * string parameter. Note that when using SSPI we still leave
839  * the negotiate parameter off, since we want SSPI to use the
840  * GSSAPI kerberos protocol. For actual SSPI negotiate
841  * protocol, we use AUTH_REQ_SSPI.
842  */
843 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
844  if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
845  r = pg_GSS_startup(conn, payloadlen);
846  else
847  r = pg_SSPI_startup(conn, 0, payloadlen);
848 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
849  r = pg_GSS_startup(conn, payloadlen);
850 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
851  r = pg_SSPI_startup(conn, 0, payloadlen);
852 #endif
853  if (r != STATUS_OK)
854  {
855  /* Error message already filled in. */
856  pgunlock_thread();
857  return STATUS_ERROR;
858  }
859  pgunlock_thread();
860  }
861  break;
862 
863  case AUTH_REQ_GSS_CONT:
864  {
865  int r;
866 
867  pglock_thread();
868 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
869  if (conn->usesspi)
870  r = pg_SSPI_continue(conn, payloadlen);
871  else
872  r = pg_GSS_continue(conn, payloadlen);
873 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
874  r = pg_GSS_continue(conn, payloadlen);
875 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
876  r = pg_SSPI_continue(conn, payloadlen);
877 #endif
878  if (r != STATUS_OK)
879  {
880  /* Error message already filled in. */
881  pgunlock_thread();
882  return STATUS_ERROR;
883  }
884  pgunlock_thread();
885  }
886  break;
887 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
888  /* No GSSAPI *or* SSPI support */
889  case AUTH_REQ_GSS:
890  case AUTH_REQ_GSS_CONT:
892  libpq_gettext("GSSAPI authentication not supported\n"));
893  return STATUS_ERROR;
894 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
895 
896 #ifdef ENABLE_SSPI
897  case AUTH_REQ_SSPI:
898 
899  /*
900  * SSPI has it's own startup message so libpq can decide which
901  * method to use. Indicate to pg_SSPI_startup that we want SSPI
902  * negotiation instead of Kerberos.
903  */
904  pglock_thread();
905  if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
906  {
907  /* Error message already filled in. */
908  pgunlock_thread();
909  return STATUS_ERROR;
910  }
911  pgunlock_thread();
912  break;
913 #else
914 
915  /*
916  * No SSPI support. However, if we have GSSAPI but not SSPI
917  * support, AUTH_REQ_SSPI will have been handled in the codepath
918  * for AUTH_REQ_GSSAPI above, so don't duplicate the case label in
919  * that case.
920  */
921 #if !defined(ENABLE_GSS)
922  case AUTH_REQ_SSPI:
924  libpq_gettext("SSPI authentication not supported\n"));
925  return STATUS_ERROR;
926 #endif /* !define(ENABLE_GSSAPI) */
927 #endif /* ENABLE_SSPI */
928 
929 
930  case AUTH_REQ_CRYPT:
932  libpq_gettext("Crypt authentication not supported\n"));
933  return STATUS_ERROR;
934 
935  case AUTH_REQ_MD5:
936  case AUTH_REQ_PASSWORD:
937  {
938  char *password;
939 
940  conn->password_needed = true;
941  password = conn->connhost[conn->whichhost].password;
942  if (password == NULL)
943  password = conn->pgpass;
944  if (password == NULL || password[0] == '\0')
945  {
948  return STATUS_ERROR;
949  }
950  if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
951  {
953  "fe_sendauth: error sending password authentication\n");
954  return STATUS_ERROR;
955  }
956  break;
957  }
958 
959  case AUTH_REQ_SASL:
960 
961  /*
962  * The request contains the name (as assigned by IANA) of the
963  * authentication mechanism.
964  */
965  if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
966  {
967  /* pg_SASL_init already set the error message */
968  return STATUS_ERROR;
969  }
970  break;
971 
972  case AUTH_REQ_SASL_CONT:
973  case AUTH_REQ_SASL_FIN:
974  if (conn->sasl_state == NULL)
975  {
977  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
978  return STATUS_ERROR;
979  }
980  if (pg_SASL_continue(conn, payloadlen,
981  (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
982  {
983  /* Use error message, if set already */
984  if (conn->errorMessage.len == 0)
986  "fe_sendauth: error in SASL authentication\n");
987  return STATUS_ERROR;
988  }
989  break;
990 
991  case AUTH_REQ_SCM_CREDS:
992  if (pg_local_sendauth(conn) != STATUS_OK)
993  return STATUS_ERROR;
994  break;
995 
996  default:
998  libpq_gettext("authentication method %u not supported\n"), areq);
999  return STATUS_ERROR;
1000  }
1001 
1002  return STATUS_OK;
1003 }
1004 
1005 
1006 /*
1007  * pg_fe_getauthname
1008  *
1009  * Returns a pointer to malloc'd space containing whatever name the user
1010  * has authenticated to the system. If there is an error, return NULL,
1011  * and put a suitable error message in *errorMessage if that's not NULL.
1012  */
1013 char *
1015 {
1016  char *result = NULL;
1017  const char *name = NULL;
1018 
1019 #ifdef WIN32
1020  /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1021  char username[256 + 1];
1022  DWORD namesize = sizeof(username);
1023 #else
1024  uid_t user_id = geteuid();
1025  char pwdbuf[BUFSIZ];
1026  struct passwd pwdstr;
1027  struct passwd *pw = NULL;
1028  int pwerr;
1029 #endif
1030 
1031  /*
1032  * Some users are using configure --enable-thread-safety-force, so we
1033  * might as well do the locking within our library to protect
1034  * pqGetpwuid(). In fact, application developers can use getpwuid() in
1035  * their application if they use the locking call we provide, or install
1036  * their own locking function using PQregisterThreadLock().
1037  */
1038  pglock_thread();
1039 
1040 #ifdef WIN32
1041  if (GetUserName(username, &namesize))
1042  name = username;
1043  else if (errorMessage)
1044  printfPQExpBuffer(errorMessage,
1045  libpq_gettext("user name lookup failure: error code %lu\n"),
1046  GetLastError());
1047 #else
1048  pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
1049  if (pw != NULL)
1050  name = pw->pw_name;
1051  else if (errorMessage)
1052  {
1053  if (pwerr != 0)
1054  printfPQExpBuffer(errorMessage,
1055  libpq_gettext("could not look up local user ID %d: %s\n"),
1056  (int) user_id,
1057  pqStrerror(pwerr, pwdbuf, sizeof(pwdbuf)));
1058  else
1059  printfPQExpBuffer(errorMessage,
1060  libpq_gettext("local user with ID %d does not exist\n"),
1061  (int) user_id);
1062  }
1063 #endif
1064 
1065  if (name)
1066  {
1067  result = strdup(name);
1068  if (result == NULL && errorMessage)
1069  printfPQExpBuffer(errorMessage,
1070  libpq_gettext("out of memory\n"));
1071  }
1072 
1073  pgunlock_thread();
1074 
1075  return result;
1076 }
1077 
1078 
1079 /*
1080  * PQencryptPassword -- exported routine to encrypt a password with MD5
1081  *
1082  * This function is equivalent to calling PQencryptPasswordConn with
1083  * "md5" as the encryption method, except that this doesn't require
1084  * a connection object. This function is deprecated, use
1085  * PQencryptPasswordConn instead.
1086  */
1087 char *
1088 PQencryptPassword(const char *passwd, const char *user)
1089 {
1090  char *crypt_pwd;
1091 
1092  crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
1093  if (!crypt_pwd)
1094  return NULL;
1095 
1096  if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
1097  {
1098  free(crypt_pwd);
1099  return NULL;
1100  }
1101 
1102  return crypt_pwd;
1103 }
1104 
1105 /*
1106  * PQencryptPasswordConn -- exported routine to encrypt a password
1107  *
1108  * This is intended to be used by client applications that wish to send
1109  * commands like ALTER USER joe PASSWORD 'pwd'. The password need not
1110  * be sent in cleartext if it is encrypted on the client side. This is
1111  * good because it ensures the cleartext password won't end up in logs,
1112  * pg_stat displays, etc. We export the function so that clients won't
1113  * be dependent on low-level details like whether the encryption is MD5
1114  * or something else.
1115  *
1116  * Arguments are a connection object, the cleartext password, the SQL
1117  * name of the user it is for, and a string indicating the algorithm to
1118  * use for encrypting the password. If algorithm is NULL, this queries
1119  * the server for the current 'password_encryption' value. If you wish
1120  * to avoid that, e.g. to avoid blocking, you can execute
1121  * 'show password_encryption' yourself before calling this function, and
1122  * pass it as the algorithm.
1123  *
1124  * Return value is a malloc'd string. The client may assume the string
1125  * doesn't contain any special characters that would require escaping.
1126  * On error, an error message is stored in the connection object, and
1127  * returns NULL.
1128  */
1129 char *
1130 PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
1131  const char *algorithm)
1132 {
1133 #define MAX_ALGORITHM_NAME_LEN 50
1134  char algobuf[MAX_ALGORITHM_NAME_LEN + 1];
1135  char *crypt_pwd = NULL;
1136 
1137  if (!conn)
1138  return NULL;
1139 
1140  /* If no algorithm was given, ask the server. */
1141  if (algorithm == NULL)
1142  {
1143  PGresult *res;
1144  char *val;
1145 
1146  res = PQexec(conn, "show password_encryption");
1147  if (res == NULL)
1148  {
1149  /* PQexec() should've set conn->errorMessage already */
1150  return NULL;
1151  }
1152  if (PQresultStatus(res) != PGRES_TUPLES_OK)
1153  {
1154  /* PQexec() should've set conn->errorMessage already */
1155  PQclear(res);
1156  return NULL;
1157  }
1158  if (PQntuples(res) != 1 || PQnfields(res) != 1)
1159  {
1160  PQclear(res);
1162  libpq_gettext("unexpected shape of result set returned for SHOW\n"));
1163  return NULL;
1164  }
1165  val = PQgetvalue(res, 0, 0);
1166 
1167  if (strlen(val) > MAX_ALGORITHM_NAME_LEN)
1168  {
1169  PQclear(res);
1171  libpq_gettext("password_encryption value too long\n"));
1172  return NULL;
1173  }
1174  strcpy(algobuf, val);
1175  PQclear(res);
1176 
1177  algorithm = algobuf;
1178  }
1179 
1180  /*
1181  * Also accept "on" and "off" as aliases for "md5", because
1182  * password_encryption was a boolean before PostgreSQL 10. We refuse to
1183  * send the password in plaintext even if it was "off".
1184  */
1185  if (strcmp(algorithm, "on") == 0 ||
1186  strcmp(algorithm, "off") == 0)
1187  algorithm = "md5";
1188 
1189  /*
1190  * Ok, now we know what algorithm to use
1191  */
1192  if (strcmp(algorithm, "scram-sha-256") == 0)
1193  {
1194  crypt_pwd = pg_fe_scram_build_verifier(passwd);
1195  }
1196  else if (strcmp(algorithm, "md5") == 0)
1197  {
1198  crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
1199  if (crypt_pwd)
1200  {
1201  if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
1202  {
1203  free(crypt_pwd);
1204  crypt_pwd = NULL;
1205  }
1206  }
1207  }
1208  else
1209  {
1211  libpq_gettext("unknown password encryption algorithm\n"));
1212  return NULL;
1213  }
1214 
1215  if (!crypt_pwd)
1217  libpq_gettext("out of memory\n"));
1218 
1219  return crypt_pwd;
1220 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:963
static char password[100]
Definition: streamutil.c:41
int PQnfields(const PGresult *res)
Definition: fe-exec.c:2681
#define AUTH_REQ_SSPI
Definition: pqcomm.h:174
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3067
static void error(void)
Definition: sql-dyntest.c:147
static int pg_local_sendauth(PGconn *conn)
Definition: fe-auth.c:679
int uid_t
Definition: win32.h:250
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:165
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:177
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
Definition: fe-auth.c:807
static void output(uint64 loop_count)
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
bool password_needed
Definition: libpq-int.h:408
#define AUTH_REQ_OK
Definition: pqcomm.h:165
#define AUTH_REQ_GSS
Definition: pqcomm.h:172
static int pg_SASL_init(PGconn *conn, int payloadlen)
Definition: fe-auth.c:476
char * pqStrerror(int errnum, char *strerrbuf, size_t buflen)
Definition: thread.c:61
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:521
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:731
#define STATUS_ERROR
Definition: c.h:976
#define pglock_thread()
Definition: libpq-int.h:562
return result
Definition: formatting.c:1632
#define PQnoPasswordSupplied
Definition: libpq-fe.h:512
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:197
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2673
uint32 AuthRequest
Definition: pqcomm.h:179
#define AUTH_REQ_MD5
Definition: pqcomm.h:170
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2596
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
Definition: fe-auth.c:609
#define malloc(a)
Definition: header.h:50
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:309
#define MAX_ALGORITHM_NAME_LEN
void pg_fe_scram_exchange(void *opaq, char *input, int inputlen, char **output, int *outputlen, bool *done, bool *success, PQExpBuffer errorMessage)
bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf)
Definition: md5.c:323
#define NI_MAXHOST
Definition: getaddrinfo.h:88
PGconn * conn
Definition: streamutil.c:42
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
pg_conn_host * connhost
Definition: libpq-int.h:397
static bool success
Definition: pg_basebackup.c:96
void * sasl_state
Definition: libpq-int.h:455
static char * buf
Definition: pg_test_fsync.c:66
#define SCRAM_SHA256_NAME
Definition: scram.h:17
int pqPuts(const char *s, PGconn *conn)
Definition: fe-misc.c:181
#define AUTH_REQ_CRYPT
Definition: pqcomm.h:169
char * pguser
Definition: libpq-int.h:342
#define STATUS_OK
Definition: c.h:975
void * pg_fe_scram_init(const char *username, const char *password)
Definition: fe-auth-scram.c:84
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
pgsocket sock
Definition: libpq-int.h:400
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1014
PQExpBufferData errorMessage
Definition: libpq-int.h:492
#define AUTH_REQ_KRB5
Definition: pqcomm.h:167
static char * username
Definition: initdb.c:131
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:176
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:5889
void PQclear(PGresult *res)
Definition: fe-exec.c:650
#define MD5_PASSWD_LEN
Definition: md5.h:19
#define free(a)
Definition: header.h:65
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
#define NULL
Definition: c.h:229
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:248
#define AUTH_REQ_KRB4
Definition: pqcomm.h:166
char * pgpass
Definition: libpq-int.h:343
ProtocolVersion pversion
Definition: libpq-int.h:404
char * PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm)
Definition: fe-auth.c:1130
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:589
const char * name
Definition: encode.c:521
#define AUTH_REQ_SASL
Definition: pqcomm.h:175
#define AUTH_REQ_GSS_CONT
Definition: pqcomm.h:173
char * pg_fe_scram_build_verifier(const char *password)
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result)
Definition: thread.c:95
static char * user
Definition: pg_regress.c:92
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
Definition: fe-connect.c:3866
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1846
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
#define pgunlock_thread()
Definition: libpq-int.h:563
long val
Definition: informix.c:689
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
int whichhost
Definition: libpq-int.h:396
char * PQencryptPassword(const char *passwd, const char *user)
Definition: fe-auth.c:1088
#define libpq_gettext(x)
Definition: libpq-int.h:683
#define AUTH_REQ_SCM_CREDS
Definition: pqcomm.h:171
char * password
Definition: libpq-int.h:311