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