1 /*-------------------------------------------------------------------------
4 * The front-end (client) authorization routines
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/interfaces/libpq/fe-auth.c
12 *-------------------------------------------------------------------------
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
23 #include "postgres_fe.h"
32 #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
33 #include <sys/socket.h>
34 #ifdef HAVE_SYS_UCRED_H
35 #include <sys/ucred.h>
37 #ifndef MAXHOSTNAMELEN
38 #include <netdb.h> /* for MAXHOSTNAMELEN on some */
42 #include "common/md5.h"
43 #include "common/scram-common.h"
45 #include "fe-auth-sasl.h"
50 * GSSAPI authentication system.
53 #include "fe-gssapi-common.h"
56 * Continue GSS authentication with next token as needed.
59 pg_GSS_continue(PGconn
*conn
, int payloadlen
)
64 gss_flags
= GSS_C_MUTUAL_FLAG
;
65 gss_buffer_desc ginbuf
;
66 gss_buffer_desc goutbuf
;
69 * On first call, there's no input token. On subsequent calls, read the
70 * input token into a GSS buffer.
72 if (conn
->gctx
!= GSS_C_NO_CONTEXT
)
74 ginbuf
.length
= payloadlen
;
75 ginbuf
.value
= malloc(payloadlen
);
78 libpq_append_conn_error(conn
, "out of memory allocating GSSAPI buffer (%d)",
82 if (pqGetnchar(ginbuf
.value
, payloadlen
, conn
))
85 * Shouldn't happen, because the caller should've ensured that the
86 * whole message is already in the input buffer.
98 /* finished parsing, trace server-to-client message */
100 pqTraceOutputMessage(conn
, conn
->inBuffer
+ conn
->inStart
, false);
102 /* Only try to acquire credentials if GSS delegation isn't disabled. */
103 if (!pg_GSS_have_cred_cache(&conn
->gcred
))
104 conn
->gcred
= GSS_C_NO_CREDENTIAL
;
106 if (conn
->gssdelegation
&& conn
->gssdelegation
[0] == '1')
107 gss_flags
|= GSS_C_DELEG_FLAG
;
109 maj_stat
= gss_init_sec_context(&min_stat
,
116 GSS_C_NO_CHANNEL_BINDINGS
,
117 (ginbuf
.value
== NULL
) ? GSS_C_NO_BUFFER
: &ginbuf
,
125 if (goutbuf
.length
!= 0)
128 * GSS generated data to send to the server. We don't care if it's the
129 * first or subsequent packet, just send the same kind of password
132 conn
->current_auth_response
= AUTH_RESPONSE_GSS
;
133 if (pqPacketSend(conn
, PqMsg_GSSResponse
,
134 goutbuf
.value
, goutbuf
.length
) != STATUS_OK
)
136 gss_release_buffer(&lmin_s
, &goutbuf
);
140 gss_release_buffer(&lmin_s
, &goutbuf
);
142 if (maj_stat
!= GSS_S_COMPLETE
&& maj_stat
!= GSS_S_CONTINUE_NEEDED
)
144 pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
147 gss_release_name(&lmin_s
, &conn
->gtarg_nam
);
149 gss_delete_sec_context(&lmin_s
, &conn
->gctx
, GSS_C_NO_BUFFER
);
153 if (maj_stat
== GSS_S_COMPLETE
)
155 conn
->client_finished_auth
= true;
156 gss_release_name(&lmin_s
, &conn
->gtarg_nam
);
157 conn
->gssapi_used
= true;
164 * Send initial GSS authentication token
167 pg_GSS_startup(PGconn
*conn
, int payloadlen
)
170 char *host
= conn
->connhost
[conn
->whichhost
].host
;
172 if (!(host
&& host
[0] != '\0'))
174 libpq_append_conn_error(conn
, "host name must be specified");
180 libpq_append_conn_error(conn
, "duplicate GSS authentication request");
184 ret
= pg_GSS_load_servicename(conn
);
185 if (ret
!= STATUS_OK
)
189 * Initial packet is the same as a continuation packet with no initial
192 conn
->gctx
= GSS_C_NO_CONTEXT
;
194 return pg_GSS_continue(conn
, payloadlen
);
196 #endif /* ENABLE_GSS */
201 * SSPI authentication system (Windows only)
205 pg_SSPI_error(PGconn
*conn
, const char *mprefix
, SECURITY_STATUS r
)
209 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS
|
210 FORMAT_MESSAGE_FROM_SYSTEM
,
212 sysmsg
, sizeof(sysmsg
), NULL
) == 0)
213 appendPQExpBuffer(&conn
->errorMessage
, "%s: SSPI error %x\n",
214 mprefix
, (unsigned int) r
);
216 appendPQExpBuffer(&conn
->errorMessage
, "%s: %s (%x)\n",
217 mprefix
, sysmsg
, (unsigned int) r
);
221 * Continue SSPI authentication with next token as needed.
224 pg_SSPI_continue(PGconn
*conn
, int payloadlen
)
227 CtxtHandle newContext
;
230 SecBufferDesc outbuf
;
231 SecBuffer OutBuffers
[1];
232 SecBuffer InBuffers
[1];
233 char *inputbuf
= NULL
;
235 if (conn
->sspictx
!= NULL
)
238 * On runs other than the first we have some data to send. Put this
239 * data in a SecBuffer type structure.
241 inputbuf
= malloc(payloadlen
);
244 libpq_append_conn_error(conn
, "out of memory allocating SSPI buffer (%d)",
248 if (pqGetnchar(inputbuf
, payloadlen
, conn
))
251 * Shouldn't happen, because the caller should've ensured that the
252 * whole message is already in the input buffer.
258 inbuf
.ulVersion
= SECBUFFER_VERSION
;
260 inbuf
.pBuffers
= InBuffers
;
261 InBuffers
[0].pvBuffer
= inputbuf
;
262 InBuffers
[0].cbBuffer
= payloadlen
;
263 InBuffers
[0].BufferType
= SECBUFFER_TOKEN
;
266 /* finished parsing, trace server-to-client message */
268 pqTraceOutputMessage(conn
, conn
->inBuffer
+ conn
->inStart
, false);
270 OutBuffers
[0].pvBuffer
= NULL
;
271 OutBuffers
[0].BufferType
= SECBUFFER_TOKEN
;
272 OutBuffers
[0].cbBuffer
= 0;
274 outbuf
.pBuffers
= OutBuffers
;
275 outbuf
.ulVersion
= SECBUFFER_VERSION
;
277 r
= InitializeSecurityContext(conn
->sspicred
,
280 ISC_REQ_ALLOCATE_MEMORY
,
282 SECURITY_NETWORK_DREP
,
283 (conn
->sspictx
== NULL
) ? NULL
: &inbuf
,
290 /* we don't need the input anymore */
293 if (r
!= SEC_E_OK
&& r
!= SEC_I_CONTINUE_NEEDED
)
295 pg_SSPI_error(conn
, libpq_gettext("SSPI continuation error"), r
);
300 if (conn
->sspictx
== NULL
)
302 /* On first run, transfer retrieved context handle */
303 conn
->sspictx
= malloc(sizeof(CtxtHandle
));
304 if (conn
->sspictx
== NULL
)
306 libpq_append_conn_error(conn
, "out of memory");
309 memcpy(conn
->sspictx
, &newContext
, sizeof(CtxtHandle
));
313 * If SSPI returned any data to be sent to the server (as it normally
314 * would), send this data as a password packet.
316 if (outbuf
.cBuffers
> 0)
318 if (outbuf
.cBuffers
!= 1)
321 * This should never happen, at least not for Kerberos
322 * authentication. Keep check in case it shows up with other
323 * authentication methods later.
325 appendPQExpBufferStr(&conn
->errorMessage
,
326 "SSPI returned invalid number of output buffers\n");
331 * If the negotiation is complete, there may be zero bytes to send.
332 * The server is at this point not expecting any more data, so don't
335 if (outbuf
.pBuffers
[0].cbBuffer
> 0)
337 conn
->current_auth_response
= AUTH_RESPONSE_GSS
;
338 if (pqPacketSend(conn
, PqMsg_GSSResponse
,
339 outbuf
.pBuffers
[0].pvBuffer
, outbuf
.pBuffers
[0].cbBuffer
))
341 FreeContextBuffer(outbuf
.pBuffers
[0].pvBuffer
);
345 FreeContextBuffer(outbuf
.pBuffers
[0].pvBuffer
);
349 conn
->client_finished_auth
= true;
351 /* Cleanup is handled by the code in freePGconn() */
356 * Send initial SSPI authentication token.
357 * If use_negotiate is 0, use kerberos authentication package which is
358 * compatible with Unix. If use_negotiate is 1, use the negotiate package
359 * which supports both kerberos and NTLM, but is not compatible with Unix.
362 pg_SSPI_startup(PGconn
*conn
, int use_negotiate
, int payloadlen
)
366 char *host
= conn
->connhost
[conn
->whichhost
].host
;
370 libpq_append_conn_error(conn
, "duplicate SSPI authentication request");
375 * Retrieve credentials handle
377 conn
->sspicred
= malloc(sizeof(CredHandle
));
378 if (conn
->sspicred
== NULL
)
380 libpq_append_conn_error(conn
, "out of memory");
384 r
= AcquireCredentialsHandle(NULL
,
385 use_negotiate
? "negotiate" : "kerberos",
386 SECPKG_CRED_OUTBOUND
,
395 pg_SSPI_error(conn
, libpq_gettext("could not acquire SSPI credentials"), r
);
396 free(conn
->sspicred
);
397 conn
->sspicred
= NULL
;
402 * Compute target principal name. SSPI has a different format from GSSAPI,
403 * but not more complex. We can skip the @REALM part, because Windows will
404 * fill that in for us automatically.
406 if (!(host
&& host
[0] != '\0'))
408 libpq_append_conn_error(conn
, "host name must be specified");
411 conn
->sspitarget
= malloc(strlen(conn
->krbsrvname
) + strlen(host
) + 2);
412 if (!conn
->sspitarget
)
414 libpq_append_conn_error(conn
, "out of memory");
417 sprintf(conn
->sspitarget
, "%s/%s", conn
->krbsrvname
, host
);
420 * Indicate that we're in SSPI authentication mode to make sure that
421 * pg_SSPI_continue is called next time in the negotiation.
425 return pg_SSPI_continue(conn
, payloadlen
);
427 #endif /* ENABLE_SSPI */
430 * Initialize SASL authentication exchange.
433 pg_SASL_init(PGconn
*conn
, int payloadlen
)
435 char *initialresponse
= NULL
;
436 int initialresponselen
;
437 const char *selected_mechanism
;
438 PQExpBufferData mechanism_buf
;
439 char *password
= NULL
;
442 initPQExpBuffer(&mechanism_buf
);
444 if (conn
->channel_binding
[0] == 'r' && /* require */
447 libpq_append_conn_error(conn
, "channel binding required, but SSL not in use");
451 if (conn
->sasl_state
)
453 libpq_append_conn_error(conn
, "duplicate SASL authentication request");
458 * Parse the list of SASL authentication mechanisms in the
459 * AuthenticationSASL message, and select the best mechanism that we
460 * support. Mechanisms are listed by order of decreasing importance.
462 selected_mechanism
= NULL
;
465 if (pqGets(&mechanism_buf
, conn
))
467 appendPQExpBufferStr(&conn
->errorMessage
,
468 "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
471 if (PQExpBufferDataBroken(mechanism_buf
))
474 /* An empty string indicates end of list */
475 if (mechanism_buf
.data
[0] == '\0')
479 * Select the mechanism to use. Pick SCRAM-SHA-256-PLUS over anything
480 * else if a channel binding type is set and if the client supports it
481 * (and did not set channel_binding=disable). Pick SCRAM-SHA-256 if
482 * nothing else has already been picked. If we add more mechanisms, a
483 * more refined priority mechanism might become necessary.
485 if (strcmp(mechanism_buf
.data
, SCRAM_SHA_256_PLUS_NAME
) == 0)
487 if (conn
->ssl_in_use
)
489 /* The server has offered SCRAM-SHA-256-PLUS. */
493 * The client supports channel binding, which is chosen if
494 * channel_binding is not disabled.
496 if (conn
->channel_binding
[0] != 'd') /* disable */
498 selected_mechanism
= SCRAM_SHA_256_PLUS_NAME
;
499 conn
->sasl
= &pg_scram_mech
;
500 conn
->password_needed
= true;
504 * The client does not support channel binding. If it is
505 * required, complain immediately instead of the error below
506 * which would be confusing as the server is publishing
507 * SCRAM-SHA-256-PLUS.
509 if (conn
->channel_binding
[0] == 'r') /* require */
511 libpq_append_conn_error(conn
, "channel binding is required, but client does not support it");
519 * The server offered SCRAM-SHA-256-PLUS, but the connection
520 * is not SSL-encrypted. That's not sane. Perhaps SSL was
521 * stripped by a proxy? There's no point in continuing,
522 * because the server will reject the connection anyway if we
523 * try authenticate without channel binding even though both
524 * the client and server supported it. The SCRAM exchange
525 * checks for that, to prevent downgrade attacks.
527 libpq_append_conn_error(conn
, "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection");
531 else if (strcmp(mechanism_buf
.data
, SCRAM_SHA_256_NAME
) == 0 &&
534 selected_mechanism
= SCRAM_SHA_256_NAME
;
535 conn
->sasl
= &pg_scram_mech
;
536 conn
->password_needed
= true;
540 if (!selected_mechanism
)
542 libpq_append_conn_error(conn
, "none of the server's SASL authentication mechanisms are supported");
546 if (conn
->channel_binding
[0] == 'r' && /* require */
547 strcmp(selected_mechanism
, SCRAM_SHA_256_PLUS_NAME
) != 0)
549 libpq_append_conn_error(conn
, "channel binding is required, but server did not offer an authentication method that supports channel binding");
554 * Now that the SASL mechanism has been chosen for the exchange,
555 * initialize its state information.
559 * First, select the password to use for the exchange, complaining if
560 * there isn't one and the selected SASL mechanism needs it.
562 if (conn
->password_needed
&& !conn
->scram_client_key_binary
)
564 password
= conn
->connhost
[conn
->whichhost
].password
;
565 if (password
== NULL
)
566 password
= conn
->pgpass
;
567 if (password
== NULL
|| password
[0] == '\0')
569 appendPQExpBufferStr(&conn
->errorMessage
,
570 PQnoPasswordSupplied
);
575 /* finished parsing, trace server-to-client message */
577 pqTraceOutputMessage(conn
, conn
->inBuffer
+ conn
->inStart
, false);
582 * Initialize the SASL state information with all the information gathered
583 * during the initial exchange.
585 * Note: Only tls-unique is supported for the moment.
587 conn
->sasl_state
= conn
->sasl
->init(conn
,
590 if (!conn
->sasl_state
)
593 /* Get the mechanism-specific Initial Client Response, if any */
594 status
= conn
->sasl
->exchange(conn
->sasl_state
,
596 &initialresponse
, &initialresponselen
);
598 if (status
== SASL_FAILED
)
602 * Build a SASLInitialResponse message, and send it.
604 if (pqPutMsgStart(PqMsg_SASLInitialResponse
, conn
))
606 if (pqPuts(selected_mechanism
, conn
))
610 if (pqPutInt(initialresponselen
, 4, conn
))
612 if (pqPutnchar(initialresponse
, initialresponselen
, conn
))
615 conn
->current_auth_response
= AUTH_RESPONSE_SASL_INITIAL
;
616 if (pqPutMsgEnd(conn
))
622 termPQExpBuffer(&mechanism_buf
);
623 free(initialresponse
);
628 termPQExpBuffer(&mechanism_buf
);
629 free(initialresponse
);
633 termPQExpBuffer(&mechanism_buf
);
634 free(initialresponse
);
635 libpq_append_conn_error(conn
, "out of memory");
640 * Exchange a message for SASL communication protocol with the backend.
641 * This should be used after calling pg_SASL_init to set up the status of
645 pg_SASL_continue(PGconn
*conn
, int payloadlen
, bool final
)
653 /* Read the SASL challenge from the AuthenticationSASLContinue message. */
654 challenge
= malloc(payloadlen
+ 1);
657 libpq_append_conn_error(conn
, "out of memory allocating SASL buffer (%d)",
662 if (pqGetnchar(challenge
, payloadlen
, conn
))
668 /* finished parsing, trace server-to-client message */
670 pqTraceOutputMessage(conn
, conn
->inBuffer
+ conn
->inStart
, false);
672 /* For safety and convenience, ensure the buffer is NULL-terminated. */
673 challenge
[payloadlen
] = '\0';
675 status
= conn
->sasl
->exchange(conn
->sasl_state
,
676 challenge
, payloadlen
,
677 &output
, &outputlen
);
678 free(challenge
); /* don't need the input anymore */
680 if (final
&& status
== SASL_CONTINUE
)
685 libpq_append_conn_error(conn
, "AuthenticationSASLFinal received from server, but SASL authentication was not completed");
690 * If the exchange is not completed yet, we need to make sure that the
691 * SASL mechanism has generated a message to send back.
693 if (output
== NULL
&& status
== SASL_CONTINUE
)
695 libpq_append_conn_error(conn
, "no client response found after SASL exchange success");
700 * SASL allows zero-length responses, so this check uses "output" and not
701 * "outputlen" to allow the case of an empty message.
706 * Send the SASL response to the server.
708 conn
->current_auth_response
= AUTH_RESPONSE_SASL
;
709 res
= pqPacketSend(conn
, PqMsg_SASLResponse
, output
, outputlen
);
712 if (res
!= STATUS_OK
)
716 if (status
== SASL_FAILED
)
723 pg_password_sendauth(PGconn
*conn
, const char *password
, AuthRequest areq
)
726 char *crypt_pwd
= NULL
;
727 const char *pwd_to_send
;
730 /* Read the salt from the AuthenticationMD5Password message. */
731 if (areq
== AUTH_REQ_MD5
)
733 if (pqGetnchar(md5Salt
, 4, conn
))
734 return STATUS_ERROR
; /* shouldn't happen */
737 /* finished parsing, trace server-to-client message */
739 pqTraceOutputMessage(conn
, conn
->inBuffer
+ conn
->inStart
, false);
741 /* Encrypt the password if needed. */
748 const char *errstr
= NULL
;
750 /* Allocate enough space for two MD5 hashes */
751 crypt_pwd
= malloc(2 * (MD5_PASSWD_LEN
+ 1));
754 libpq_append_conn_error(conn
, "out of memory");
758 crypt_pwd2
= crypt_pwd
+ MD5_PASSWD_LEN
+ 1;
759 if (!pg_md5_encrypt(password
, conn
->pguser
,
760 strlen(conn
->pguser
), crypt_pwd2
,
763 libpq_append_conn_error(conn
, "could not encrypt password: %s", errstr
);
767 if (!pg_md5_encrypt(crypt_pwd2
+ strlen("md5"), md5Salt
,
768 4, crypt_pwd
, &errstr
))
770 libpq_append_conn_error(conn
, "could not encrypt password: %s", errstr
);
775 pwd_to_send
= crypt_pwd
;
778 case AUTH_REQ_PASSWORD
:
779 pwd_to_send
= password
;
784 conn
->current_auth_response
= AUTH_RESPONSE_PASSWORD
;
785 ret
= pqPacketSend(conn
, PqMsg_PasswordMessage
,
786 pwd_to_send
, strlen(pwd_to_send
) + 1);
792 * Translate a disallowed AuthRequest code into an error message.
795 auth_method_description(AuthRequest areq
)
799 case AUTH_REQ_PASSWORD
:
800 return libpq_gettext("server requested a cleartext password");
802 return libpq_gettext("server requested a hashed password");
804 case AUTH_REQ_GSS_CONT
:
805 return libpq_gettext("server requested GSSAPI authentication");
807 return libpq_gettext("server requested SSPI authentication");
809 case AUTH_REQ_SASL_CONT
:
810 case AUTH_REQ_SASL_FIN
:
811 return libpq_gettext("server requested SASL authentication");
814 return libpq_gettext("server requested an unknown authentication type");
818 * Convenience macro for checking the allowed_auth_methods bitmask. Caller
819 * must ensure that type is not greater than 31 (high bit of the bitmask).
821 #define auth_method_allowed(conn, type) \
822 (((conn)->allowed_auth_methods & (1 << (type))) != 0)
825 * Verify that the authentication request is expected, given the connection
826 * parameters. This is especially important when the client wishes to
827 * authenticate the server before any sensitive information is exchanged.
830 check_expected_areq(AuthRequest areq
, PGconn
*conn
)
833 const char *reason
= NULL
;
835 StaticAssertDecl((sizeof(conn
->allowed_auth_methods
) * CHAR_BIT
) > AUTH_REQ_MAX
,
836 "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask");
838 if (conn
->sslcertmode
[0] == 'r' /* require */
839 && areq
== AUTH_REQ_OK
)
842 * Trade off a little bit of complexity to try to get these error
843 * messages as precise as possible.
845 if (!conn
->ssl_cert_requested
)
847 libpq_append_conn_error(conn
, "server did not request an SSL certificate");
850 else if (!conn
->ssl_cert_sent
)
852 libpq_append_conn_error(conn
, "server accepted connection without a valid SSL certificate");
858 * If the user required a specific auth method, or specified an allowed
859 * set, then reject all others here, and make sure the server actually
860 * completes an authentication exchange.
862 if (conn
->require_auth
)
869 * Check to make sure we've actually finished our exchange (or
870 * else that the user has allowed an authentication-less
873 * If the user has allowed both SCRAM and unauthenticated
874 * (trust) connections, then this check will silently accept
875 * partial SCRAM exchanges, where a misbehaving server does
876 * not provide its verifier before sending an OK. This is
877 * consistent with historical behavior, but it may be a point
878 * to revisit in the future, since it could allow a server
879 * that doesn't know the user's password to silently harvest
880 * material for a brute force attack.
882 if (!conn
->auth_required
|| conn
->client_finished_auth
)
886 * No explicit authentication request was made by the server
887 * -- or perhaps it was made and not completed, in the case of
888 * SCRAM -- but there is one special case to check. If the
889 * user allowed "gss", then a GSS-encrypted channel also
890 * satisfies the check.
893 if (auth_method_allowed(conn
, AUTH_REQ_GSS
) && conn
->gssenc
)
896 * If implicit GSS auth has already been performed via GSS
897 * encryption, we don't need to have performed an
898 * AUTH_REQ_GSS exchange. This allows require_auth=gss to
899 * be combined with gssencmode, since there won't be an
900 * explicit authentication request in that case.
906 reason
= libpq_gettext("server did not complete authentication");
912 case AUTH_REQ_PASSWORD
:
915 case AUTH_REQ_GSS_CONT
:
918 case AUTH_REQ_SASL_CONT
:
919 case AUTH_REQ_SASL_FIN
:
922 * We don't handle these with the default case, to avoid
923 * bit-shifting past the end of the allowed_auth_methods mask
924 * if the server sends an unexpected AuthRequest.
926 result
= auth_method_allowed(conn
, areq
);
938 reason
= auth_method_description(areq
);
940 libpq_append_conn_error(conn
, "authentication method requirement \"%s\" failed: %s",
941 conn
->require_auth
, reason
);
946 * When channel_binding=require, we must protect against two cases: (1) we
947 * must not respond to non-SASL authentication requests, which might leak
948 * information such as the client's password; and (2) even if we receive
949 * AUTH_REQ_OK, we still must ensure that channel binding has happened in
950 * order to authenticate the server.
952 if (conn
->channel_binding
[0] == 'r' /* require */ )
957 case AUTH_REQ_SASL_CONT
:
958 case AUTH_REQ_SASL_FIN
:
961 if (!conn
->sasl
|| !conn
->sasl
->channel_bound(conn
->sasl_state
))
963 libpq_append_conn_error(conn
, "channel binding required, but server authenticated client without channel binding");
968 libpq_append_conn_error(conn
, "channel binding required but not supported by server's authentication request");
979 * client demux routine for processing an authentication request
981 * The server has sent us an authentication challenge (or OK). Send an
982 * appropriate response. The caller has ensured that the whole message is
983 * now in the input buffer, and has already read the type and length of
984 * it. We are responsible for reading any remaining extra data, specific
985 * to the authentication method. 'payloadlen' is the remaining length in
989 pg_fe_sendauth(AuthRequest areq
, int payloadlen
, PGconn
*conn
)
993 if (!check_expected_areq(areq
, conn
))
1002 libpq_append_conn_error(conn
, "Kerberos 4 authentication not supported");
1003 return STATUS_ERROR
;
1006 libpq_append_conn_error(conn
, "Kerberos 5 authentication not supported");
1007 return STATUS_ERROR
;
1009 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
1011 #if !defined(ENABLE_SSPI)
1012 /* no native SSPI, so use GSSAPI library for it */
1021 * If we have both GSS and SSPI support compiled in, use SSPI
1022 * support by default. This is overridable by a connection
1023 * string parameter. Note that when using SSPI we still leave
1024 * the negotiate parameter off, since we want SSPI to use the
1025 * GSSAPI kerberos protocol. For actual SSPI negotiate
1026 * protocol, we use AUTH_REQ_SSPI.
1028 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1029 if (conn
->gsslib
&& (pg_strcasecmp(conn
->gsslib
, "gssapi") == 0))
1030 r
= pg_GSS_startup(conn
, payloadlen
);
1032 r
= pg_SSPI_startup(conn
, 0, payloadlen
);
1033 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1034 r
= pg_GSS_startup(conn
, payloadlen
);
1035 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1036 r
= pg_SSPI_startup(conn
, 0, payloadlen
);
1040 /* Error message already filled in. */
1042 return STATUS_ERROR
;
1048 case AUTH_REQ_GSS_CONT
:
1053 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1055 r
= pg_SSPI_continue(conn
, payloadlen
);
1057 r
= pg_GSS_continue(conn
, payloadlen
);
1058 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1059 r
= pg_GSS_continue(conn
, payloadlen
);
1060 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1061 r
= pg_SSPI_continue(conn
, payloadlen
);
1065 /* Error message already filled in. */
1067 return STATUS_ERROR
;
1072 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1073 /* No GSSAPI *or* SSPI support */
1075 case AUTH_REQ_GSS_CONT
:
1076 libpq_append_conn_error(conn
, "GSSAPI authentication not supported");
1077 return STATUS_ERROR
;
1078 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1084 * SSPI has its own startup message so libpq can decide which
1085 * method to use. Indicate to pg_SSPI_startup that we want SSPI
1086 * negotiation instead of Kerberos.
1089 if (pg_SSPI_startup(conn
, 1, payloadlen
) != STATUS_OK
)
1091 /* Error message already filled in. */
1093 return STATUS_ERROR
;
1100 * No SSPI support. However, if we have GSSAPI but not SSPI
1101 * support, AUTH_REQ_SSPI will have been handled in the codepath
1102 * for AUTH_REQ_GSS above, so don't duplicate the case label in
1105 #if !defined(ENABLE_GSS)
1107 libpq_append_conn_error(conn
, "SSPI authentication not supported");
1108 return STATUS_ERROR
;
1109 #endif /* !define(ENABLE_GSS) */
1110 #endif /* ENABLE_SSPI */
1113 case AUTH_REQ_CRYPT
:
1114 libpq_append_conn_error(conn
, "Crypt authentication not supported");
1115 return STATUS_ERROR
;
1118 case AUTH_REQ_PASSWORD
:
1122 conn
->password_needed
= true;
1123 password
= conn
->connhost
[conn
->whichhost
].password
;
1124 if (password
== NULL
)
1125 password
= conn
->pgpass
;
1126 if (password
== NULL
|| password
[0] == '\0')
1128 appendPQExpBufferStr(&conn
->errorMessage
,
1129 PQnoPasswordSupplied
);
1130 return STATUS_ERROR
;
1132 if (pg_password_sendauth(conn
, password
, areq
) != STATUS_OK
)
1134 appendPQExpBufferStr(&conn
->errorMessage
,
1135 "fe_sendauth: error sending password authentication\n");
1136 return STATUS_ERROR
;
1139 /* We expect no further authentication requests. */
1140 conn
->client_finished_auth
= true;
1147 * The request contains the name (as assigned by IANA) of the
1148 * authentication mechanism.
1150 if (pg_SASL_init(conn
, payloadlen
) != STATUS_OK
)
1152 /* pg_SASL_init already set the error message */
1153 return STATUS_ERROR
;
1157 case AUTH_REQ_SASL_CONT
:
1158 case AUTH_REQ_SASL_FIN
:
1159 if (conn
->sasl_state
== NULL
)
1161 appendPQExpBufferStr(&conn
->errorMessage
,
1162 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1163 return STATUS_ERROR
;
1165 oldmsglen
= conn
->errorMessage
.len
;
1166 if (pg_SASL_continue(conn
, payloadlen
,
1167 (areq
== AUTH_REQ_SASL_FIN
)) != STATUS_OK
)
1169 /* Use this message if pg_SASL_continue didn't supply one */
1170 if (conn
->errorMessage
.len
== oldmsglen
)
1171 appendPQExpBufferStr(&conn
->errorMessage
,
1172 "fe_sendauth: error in SASL authentication\n");
1173 return STATUS_ERROR
;
1178 libpq_append_conn_error(conn
, "authentication method %u not supported", areq
);
1179 return STATUS_ERROR
;
1189 * Returns a pointer to malloc'd space containing the name of the
1190 * specified user_id. If there is an error, return NULL, and append
1191 * a suitable error message to *errorMessage if that's not NULL.
1193 * Caution: on Windows, the user_id argument is ignored, and we always
1194 * fetch the current user's name.
1197 pg_fe_getusername(uid_t user_id
, PQExpBuffer errorMessage
)
1199 char *result
= NULL
;
1200 const char *name
= NULL
;
1203 /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1204 char username
[256 + 1];
1205 DWORD namesize
= sizeof(username
);
1207 struct passwd pwbuf
;
1208 struct passwd
*pw
= NULL
;
1214 if (GetUserName(username
, &namesize
))
1216 else if (errorMessage
)
1217 libpq_append_error(errorMessage
,
1218 "user name lookup failure: error code %lu",
1221 rc
= getpwuid_r(user_id
, &pwbuf
, buf
, sizeof buf
, &pw
);
1226 libpq_append_error(errorMessage
, "could not look up local user ID %ld: %m", (long) user_id
);
1231 libpq_append_error(errorMessage
, "local user with ID %ld does not exist", (long) user_id
);
1239 result
= strdup(name
);
1240 if (result
== NULL
&& errorMessage
)
1241 libpq_append_error(errorMessage
, "out of memory");
1250 * Returns a pointer to malloc'd space containing whatever name the user
1251 * has authenticated to the system. If there is an error, return NULL,
1252 * and append a suitable error message to *errorMessage if that's not NULL.
1255 pg_fe_getauthname(PQExpBuffer errorMessage
)
1258 return pg_fe_getusername(0, errorMessage
);
1260 return pg_fe_getusername(geteuid(), errorMessage
);
1266 * PQencryptPassword -- exported routine to encrypt a password with MD5
1268 * This function is equivalent to calling PQencryptPasswordConn with
1269 * "md5" as the encryption method, except that this doesn't require
1270 * a connection object. This function is deprecated, use
1271 * PQencryptPasswordConn instead.
1274 PQencryptPassword(const char *passwd
, const char *user
)
1277 const char *errstr
= NULL
;
1279 crypt_pwd
= malloc(MD5_PASSWD_LEN
+ 1);
1283 if (!pg_md5_encrypt(passwd
, user
, strlen(user
), crypt_pwd
, &errstr
))
1293 * PQencryptPasswordConn -- exported routine to encrypt a password
1295 * This is intended to be used by client applications that wish to send
1296 * commands like ALTER USER joe PASSWORD 'pwd'. The password need not
1297 * be sent in cleartext if it is encrypted on the client side. This is
1298 * good because it ensures the cleartext password won't end up in logs,
1299 * pg_stat displays, etc. We export the function so that clients won't
1300 * be dependent on low-level details like whether the encryption is MD5
1301 * or something else.
1303 * Arguments are a connection object, the cleartext password, the SQL
1304 * name of the user it is for, and a string indicating the algorithm to
1305 * use for encrypting the password. If algorithm is NULL, this queries
1306 * the server for the current 'password_encryption' value. If you wish
1307 * to avoid that, e.g. to avoid blocking, you can execute
1308 * 'show password_encryption' yourself before calling this function, and
1309 * pass it as the algorithm.
1311 * Return value is a malloc'd string. The client may assume the string
1312 * doesn't contain any special characters that would require escaping.
1313 * On error, an error message is stored in the connection object, and
1317 PQencryptPasswordConn(PGconn
*conn
, const char *passwd
, const char *user
,
1318 const char *algorithm
)
1320 #define MAX_ALGORITHM_NAME_LEN 50
1321 char algobuf
[MAX_ALGORITHM_NAME_LEN
+ 1];
1322 char *crypt_pwd
= NULL
;
1327 pqClearConnErrorState(conn
);
1329 /* If no algorithm was given, ask the server. */
1330 if (algorithm
== NULL
)
1335 res
= PQexec(conn
, "show password_encryption");
1338 /* PQexec() should've set conn->errorMessage already */
1341 if (PQresultStatus(res
) != PGRES_TUPLES_OK
)
1343 /* PQexec() should've set conn->errorMessage already */
1347 if (PQntuples(res
) != 1 || PQnfields(res
) != 1)
1350 libpq_append_conn_error(conn
, "unexpected shape of result set returned for SHOW");
1353 val
= PQgetvalue(res
, 0, 0);
1355 if (strlen(val
) > MAX_ALGORITHM_NAME_LEN
)
1358 libpq_append_conn_error(conn
, "\"password_encryption\" value too long");
1361 strcpy(algobuf
, val
);
1364 algorithm
= algobuf
;
1368 * Also accept "on" and "off" as aliases for "md5", because
1369 * password_encryption was a boolean before PostgreSQL 10. We refuse to
1370 * send the password in plaintext even if it was "off".
1372 if (strcmp(algorithm
, "on") == 0 ||
1373 strcmp(algorithm
, "off") == 0)
1377 * Ok, now we know what algorithm to use
1379 if (strcmp(algorithm
, "scram-sha-256") == 0)
1381 const char *errstr
= NULL
;
1383 crypt_pwd
= pg_fe_scram_build_secret(passwd
,
1384 conn
->scram_sha_256_iterations
,
1387 libpq_append_conn_error(conn
, "could not encrypt password: %s", errstr
);
1389 else if (strcmp(algorithm
, "md5") == 0)
1391 crypt_pwd
= malloc(MD5_PASSWD_LEN
+ 1);
1394 const char *errstr
= NULL
;
1396 if (!pg_md5_encrypt(passwd
, user
, strlen(user
), crypt_pwd
, &errstr
))
1398 libpq_append_conn_error(conn
, "could not encrypt password: %s", errstr
);
1404 libpq_append_conn_error(conn
, "out of memory");
1408 libpq_append_conn_error(conn
, "unrecognized password encryption algorithm \"%s\"",
1417 * PQchangePassword -- exported routine to change a password
1419 * This is intended to be used by client applications that wish to
1420 * change the password for a user. The password is not sent in
1421 * cleartext because it is encrypted on the client side. This is
1422 * good because it ensures the cleartext password is never known by
1423 * the server, and therefore won't end up in logs, pg_stat displays,
1424 * etc. The password encryption is performed by PQencryptPasswordConn(),
1425 * which is passed a NULL for the algorithm argument. Hence encryption
1426 * is done according to the server's password_encryption
1427 * setting. We export the function so that clients won't be dependent
1428 * on the implementation specific details with respect to how the
1429 * server changes passwords.
1431 * Arguments are a connection object, the SQL name of the target user,
1432 * and the cleartext password.
1434 * Return value is the PGresult of the executed ALTER USER statement
1435 * or NULL if we never get there. The caller is responsible to PQclear()
1436 * the returned PGresult.
1438 * PQresultStatus() should be called to check the return value for errors,
1439 * and PQerrorMessage() used to get more information about such errors.
1442 PQchangePassword(PGconn
*conn
, const char *user
, const char *passwd
)
1444 char *encrypted_password
= PQencryptPasswordConn(conn
, passwd
,
1447 if (!encrypted_password
)
1449 /* PQencryptPasswordConn() already registered the error */
1454 char *fmtpw
= PQescapeLiteral(conn
, encrypted_password
,
1455 strlen(encrypted_password
));
1457 /* no longer needed, so clean up now */
1458 PQfreemem(encrypted_password
);
1462 /* PQescapeLiteral() already registered the error */
1467 char *fmtuser
= PQescapeIdentifier(conn
, user
, strlen(user
));
1471 /* PQescapeIdentifier() already registered the error */
1477 PQExpBufferData buf
;
1480 initPQExpBuffer(&buf
);
1481 printfPQExpBuffer(&buf
, "ALTER USER %s PASSWORD %s",
1484 res
= PQexec(conn
, buf
.data
);
1487 termPQExpBuffer(&buf
);