32 #ifdef HAVE_SYS_UCRED_H 33 #include <sys/ucred.h> 35 #ifndef MAXHOSTNAMELEN 62 gss_buffer_desc ginbuf;
63 gss_buffer_desc goutbuf;
69 if (conn->gctx != GSS_C_NO_CONTEXT)
71 ginbuf.length = payloadlen;
72 ginbuf.value =
malloc(payloadlen);
76 libpq_gettext(
"out of memory allocating GSSAPI buffer (%d)\n"),
80 if (
pqGetnchar(ginbuf.value, payloadlen, conn))
96 maj_stat = gss_init_sec_context(&min_stat,
103 GSS_C_NO_CHANNEL_BINDINGS,
104 (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
113 if (goutbuf.length != 0)
121 goutbuf.value, goutbuf.length) !=
STATUS_OK)
123 gss_release_buffer(&lmin_s, &goutbuf);
127 gss_release_buffer(&lmin_s, &goutbuf);
129 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
134 gss_release_name(&lmin_s, &conn->gtarg_nam);
136 gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
140 if (maj_stat == GSS_S_COMPLETE)
141 gss_release_name(&lmin_s, &conn->gtarg_nam);
150 pg_GSS_startup(
PGconn *conn,
int payloadlen)
155 if (!(host && host[0] !=
'\0'))
177 conn->gctx = GSS_C_NO_CONTEXT;
179 return pg_GSS_continue(conn, payloadlen);
190 pg_SSPI_error(
PGconn *conn,
const char *mprefix, SECURITY_STATUS r)
194 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
195 FORMAT_MESSAGE_FROM_SYSTEM,
197 sysmsg,
sizeof(sysmsg), NULL) == 0)
199 mprefix, (
unsigned int) r);
202 mprefix, sysmsg, (
unsigned int) r);
209 pg_SSPI_continue(
PGconn *conn,
int payloadlen)
212 CtxtHandle newContext;
215 SecBufferDesc outbuf;
216 SecBuffer OutBuffers[1];
217 SecBuffer InBuffers[1];
218 char *inputbuf = NULL;
220 if (conn->sspictx != NULL)
226 inputbuf =
malloc(payloadlen);
230 libpq_gettext(
"out of memory allocating SSPI buffer (%d)\n"),
244 inbuf.ulVersion = SECBUFFER_VERSION;
246 inbuf.pBuffers = InBuffers;
247 InBuffers[0].pvBuffer = inputbuf;
248 InBuffers[0].cbBuffer = payloadlen;
249 InBuffers[0].BufferType = SECBUFFER_TOKEN;
252 OutBuffers[0].pvBuffer = NULL;
253 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
254 OutBuffers[0].cbBuffer = 0;
256 outbuf.pBuffers = OutBuffers;
257 outbuf.ulVersion = SECBUFFER_VERSION;
259 r = InitializeSecurityContext(conn->sspicred,
262 ISC_REQ_ALLOCATE_MEMORY,
264 SECURITY_NETWORK_DREP,
265 (conn->sspictx == NULL) ? NULL : &inbuf,
276 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
278 pg_SSPI_error(conn,
libpq_gettext(
"SSPI continuation error"), r);
283 if (conn->sspictx == NULL)
286 conn->sspictx =
malloc(
sizeof(CtxtHandle));
287 if (conn->sspictx == NULL)
293 memcpy(conn->sspictx, &newContext,
sizeof(CtxtHandle));
300 if (outbuf.cBuffers > 0)
302 if (outbuf.cBuffers != 1)
310 "SSPI returned invalid number of output buffers\n");
319 if (outbuf.pBuffers[0].cbBuffer > 0)
322 outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
324 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
328 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
342 pg_SSPI_startup(
PGconn *conn,
int use_negotiate,
int payloadlen)
358 conn->sspicred =
malloc(
sizeof(CredHandle));
359 if (conn->sspicred == NULL)
366 r = AcquireCredentialsHandle(NULL,
367 use_negotiate ?
"negotiate" :
"kerberos",
368 SECPKG_CRED_OUTBOUND,
377 pg_SSPI_error(conn,
libpq_gettext(
"could not acquire SSPI credentials"), r);
378 free(conn->sspicred);
379 conn->sspicred = NULL;
388 if (!(host && host[0] !=
'\0'))
395 if (!conn->sspitarget)
409 return pg_SSPI_continue(conn, payloadlen);
419 char *initialresponse = NULL;
420 int initialresponselen;
423 const char *selected_mechanism;
433 libpq_gettext(
"channel binding required, but SSL not in use\n"));
450 selected_mechanism = NULL;
453 if (
pqGets(&mechanism_buf, conn))
456 "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
463 if (mechanism_buf.
data[0] ==
'\0')
479 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH 496 libpq_gettext(
"channel binding is required, but client does not support it\n"));
513 libpq_gettext(
"server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n"));
522 if (!selected_mechanism)
525 libpq_gettext(
"none of the server's SASL authentication mechanisms are supported\n"));
533 libpq_gettext(
"channel binding is required, but server did not offer an authentication method that supports channel binding\n"));
549 if (password == NULL)
551 if (password == NULL || password[0] ==
'\0')
573 &initialresponse, &initialresponselen,
576 if (done && !success)
584 if (
pqPuts(selected_mechanism, conn))
588 if (
pqPutInt(initialresponselen, 4, conn))
590 if (
pqPutnchar(initialresponse, initialresponselen, conn))
600 free(initialresponse);
607 free(initialresponse);
613 free(initialresponse);
635 challenge =
malloc(payloadlen + 1);
639 libpq_gettext(
"out of memory allocating SASL buffer (%d)\n"),
650 challenge[payloadlen] =
'\0';
653 challenge, payloadlen,
664 libpq_gettext(
"AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
679 if (done && !success)
697 #ifdef HAVE_STRUCT_CMSGCRED 701 struct cmsghdr *cmsg;
705 unsigned char buf[CMSG_SPACE(
sizeof(
struct cmsgcred))];
716 memset(&msg, 0,
sizeof(msg));
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;
729 if (sendmsg(conn->
sock, &msg, 0) == -1)
734 "pg_local_sendauth: sendmsg: %s\n",
741 libpq_gettext(
"SCM_CRED authentication method not supported\n"));
750 char *crypt_pwd = NULL;
751 const char *pwd_to_send;
780 strlen(conn->
pguser), crypt_pwd2))
792 pwd_to_send = crypt_pwd;
801 ret =
pqPacketSend(conn,
'p', pwd_to_send, strlen(pwd_to_send) + 1);
836 libpq_gettext(
"channel binding required, but server authenticated client without channel binding\n"));
842 libpq_gettext(
"channel binding required but not supported by server's authentication request\n"));
885 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI) 887 #if !defined(ENABLE_SSPI) 904 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI) 906 r = pg_GSS_startup(conn, payloadlen);
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);
929 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI) 931 r = pg_SSPI_continue(conn, payloadlen);
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);
966 if (pg_SSPI_startup(conn, 1, payloadlen) !=
STATUS_OK)
982 #if !defined(ENABLE_GSS) 1003 if (password == NULL)
1005 if (password == NULL || password[0] ==
'\0')
1014 "fe_sendauth: error sending password authentication\n");
1038 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1048 "fe_sendauth: error in SASL authentication\n");
1060 libpq_gettext(
"authentication method %u not supported\n"), areq);
1078 char *result = NULL;
1079 const char *
name = NULL;
1086 uid_t user_id = geteuid();
1087 char pwdbuf[BUFSIZ];
1088 struct passwd pwdstr;
1089 struct passwd *pw = NULL;
1103 if (GetUserName(username, &namesize))
1105 else if (errorMessage)
1107 libpq_gettext(
"user name lookup failure: error code %lu\n"),
1110 pwerr =
pqGetpwuid(user_id, &pwdstr, pwdbuf,
sizeof(pwdbuf), &pw);
1113 else if (errorMessage)
1129 result = strdup(name);
1130 if (result == NULL && errorMessage)
1193 const char *algorithm)
1195 #define MAX_ALGORITHM_NAME_LEN 50 1197 char *crypt_pwd = NULL;
1205 if (algorithm == NULL)
1210 res =
PQexec(conn,
"show password_encryption");
1226 libpq_gettext(
"unexpected shape of result set returned for SHOW\n"));
1238 strcpy(algobuf, val);
1241 algorithm = algobuf;
1249 if (strcmp(algorithm,
"on") == 0 ||
1250 strcmp(algorithm,
"off") == 0)
1256 if (strcmp(algorithm,
"scram-sha-256") == 0)
1260 else if (strcmp(algorithm,
"md5") == 0)
1275 libpq_gettext(
"unrecognized password encryption algorithm \"%s\"\n"),
int pqFlush(PGconn *conn)
int PQnfields(const PGresult *res)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
#define SCRAM_SHA_256_NAME
static int pg_local_sendauth(PGconn *conn)
int pqGets(PQExpBuffer buf, PGconn *conn)
#define AUTH_REQ_SASL_FIN
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
static void output(uint64 loop_count)
void termPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
static int pg_SASL_init(PGconn *conn, int payloadlen)
#define PG_STRERROR_R_BUFLEN
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
#define PQnoPasswordSupplied
void pg_fe_scram_exchange(void *opaq, char *input, int inputlen, char **output, int *outputlen, bool *done, bool *success)
int pg_strcasecmp(const char *s1, const char *s2)
int pqGetnchar(char *s, size_t len, PGconn *conn)
int PQntuples(const PGresult *res)
bool pg_fe_scram_channel_bound(void *opaq)
ExecStatusType PQresultStatus(const PGresult *res)
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
int pqPutInt(int value, size_t bytes, PGconn *conn)
#define MAX_ALGORITHM_NAME_LEN
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
char * pg_fe_scram_build_secret(const char *password)
#define SCRAM_SHA_256_PLUS_NAME
bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf)
int pqPuts(const char *s, PGconn *conn)
#define AUTH_REQ_PASSWORD
char * pg_fe_getauthname(PQExpBuffer errorMessage)
PQExpBufferData errorMessage
#define AUTH_REQ_SASL_CONT
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
void PQclear(PGresult *res)
#define PQExpBufferDataBroken(buf)
int pqPutnchar(const char *s, size_t len, PGconn *conn)
char * PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm)
int pg_GSS_load_servicename(PGconn *conn)
int pqPutMsgStart(char msg_type, PGconn *conn)
int pqPutMsgEnd(PGconn *conn)
void * pg_fe_scram_init(PGconn *conn, const char *password, const char *sasl_mechanism)
#define AUTH_REQ_GSS_CONT
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result)
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
static bool check_expected_areq(AuthRequest areq, PGconn *conn)
PGresult * PQexec(PGconn *conn, const char *query)
void resetPQExpBuffer(PQExpBuffer str)
#define pgunlock_thread()
void initPQExpBuffer(PQExpBuffer str)
char * PQencryptPassword(const char *passwd, const char *user)
#define AUTH_REQ_SCM_CREDS