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