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"),
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);
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)
283 if (
conn->sspictx == NULL)
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)
359 if (
conn->sspicred == NULL)
366 r = AcquireCredentialsHandle(NULL,
367 use_negotiate ?
"negotiate" :
"kerberos",
368 SECPKG_CRED_OUTBOUND,
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;
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
499 libpq_gettext(
"channel binding is required, but client does not support it\n"));
516 libpq_gettext(
"server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n"));
528 if (!selected_mechanism)
531 libpq_gettext(
"none of the server's SASL authentication mechanisms are supported\n"));
539 libpq_gettext(
"channel binding is required, but server did not offer an authentication method that supports channel binding\n"));
581 &initialresponse, &initialresponselen,
608 free(initialresponse);
615 free(initialresponse);
621 free(initialresponse);
643 challenge =
malloc(payloadlen + 1);
647 libpq_gettext(
"out of memory allocating SASL buffer (%d)\n"),
658 challenge[payloadlen] =
'\0';
661 challenge, payloadlen,
672 libpq_gettext(
"AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
680 if (
output == NULL && !done)
683 libpq_gettext(
"no client response found after SASL exchange success\n"));
721 #ifdef HAVE_STRUCT_CMSGCRED
725 struct cmsghdr *cmsg;
729 unsigned char buf[CMSG_SPACE(
sizeof(
struct cmsgcred))];
740 memset(&msg, 0,
sizeof(msg));
745 memset(&cmsgbuf, 0,
sizeof(cmsgbuf));
746 msg.msg_control = &cmsgbuf.buf;
747 msg.msg_controllen =
sizeof(cmsgbuf.buf);
748 cmsg = CMSG_FIRSTHDR(&msg);
749 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct cmsgcred));
750 cmsg->cmsg_level = SOL_SOCKET;
751 cmsg->cmsg_type = SCM_CREDS;
753 if (sendmsg(
conn->
sock, &msg, 0) == -1)
758 "pg_local_sendauth: sendmsg: %s\n",
765 libpq_gettext(
"SCM_CRED authentication method not supported\n"));
774 char *crypt_pwd = NULL;
775 const char *pwd_to_send;
792 const char *errstr = NULL;
815 4, crypt_pwd, &errstr))
824 pwd_to_send = crypt_pwd;
868 libpq_gettext(
"channel binding required, but server authenticated client without channel binding\n"));
874 libpq_gettext(
"channel binding required but not supported by server's authentication request\n"));
917 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
919 #if !defined(ENABLE_SSPI)
936 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
938 r = pg_GSS_startup(
conn, payloadlen);
940 r = pg_SSPI_startup(
conn, 0, payloadlen);
941 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
942 r = pg_GSS_startup(
conn, payloadlen);
943 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
944 r = pg_SSPI_startup(
conn, 0, payloadlen);
961 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
963 r = pg_SSPI_continue(
conn, payloadlen);
965 r = pg_GSS_continue(
conn, payloadlen);
966 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
967 r = pg_GSS_continue(
conn, payloadlen);
968 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
969 r = pg_SSPI_continue(
conn, payloadlen);
1014 #if !defined(ENABLE_GSS)
1046 "fe_sendauth: error sending password authentication\n");
1070 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1080 "fe_sendauth: error in SASL authentication\n");
1092 libpq_gettext(
"authentication method %u not supported\n"), areq);
1113 char *result = NULL;
1114 const char *
name = NULL;
1121 char pwdbuf[BUFSIZ];
1134 if (GetUserName(
username, &namesize))
1136 else if (errorMessage)
1138 libpq_gettext(
"user name lookup failure: error code %lu\n"),
1143 else if (errorMessage)
1149 result = strdup(
name);
1150 if (result == NULL && errorMessage)
1190 const char *errstr = NULL;
1231 const char *algorithm)
1233 #define MAX_ALGORITHM_NAME_LEN 50
1235 char *crypt_pwd = NULL;
1243 if (algorithm == NULL)
1264 libpq_gettext(
"unexpected shape of result set returned for SHOW\n"));
1276 strcpy(algobuf,
val);
1279 algorithm = algobuf;
1287 if (strcmp(algorithm,
"on") == 0 ||
1288 strcmp(algorithm,
"off") == 0)
1294 if (strcmp(algorithm,
"scram-sha-256") == 0)
1296 const char *errstr = NULL;
1304 else if (strcmp(algorithm,
"md5") == 0)
1309 const char *errstr = NULL;
1327 libpq_gettext(
"unrecognized password encryption algorithm \"%s\"\n"),
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
static void PGresult * res
char * pg_fe_scram_build_secret(const char *password, const char **errstr)
const pg_fe_sasl_mech pg_scram_mech
#define MAX_ALGORITHM_NAME_LEN
static bool check_expected_areq(AuthRequest areq, PGconn *conn)
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
static int pg_SASL_init(PGconn *conn, int payloadlen)
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
char * PQencryptPassword(const char *passwd, const char *user)
static int pg_local_sendauth(PGconn *conn)
char * pg_fe_getauthname(PQExpBuffer errorMessage)
char * PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm)
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
ExecStatusType PQresultStatus(const PGresult *res)
void PQclear(PGresult *res)
int PQntuples(const PGresult *res)
PGresult * PQexec(PGconn *conn, const char *query)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQnfields(const PGresult *res)
int pg_GSS_load_servicename(PGconn *conn)
int pqPutInt(int value, size_t bytes, PGconn *conn)
int pqFlush(PGconn *conn)
int pqPutMsgStart(char msg_type, PGconn *conn)
int pqGetnchar(char *s, size_t len, PGconn *conn)
int pqGets(PQExpBuffer buf, PGconn *conn)
int pqPutnchar(const char *s, size_t len, PGconn *conn)
int pqPuts(const char *s, PGconn *conn)
int pqPutMsgEnd(PGconn *conn)
#define PQnoPasswordSupplied
#define pqClearConnErrorState(conn)
#define pgunlock_thread()
Assert(fmt[strlen(fmt) - 1] !='\n')
bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf, const char **errstr)
static void output(uint64 loop_count)
#define PG_STRERROR_R_BUFLEN
int pg_strcasecmp(const char *s1, const char *s2)
bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen)
#define AUTH_REQ_SASL_CONT
#define AUTH_REQ_PASSWORD
#define AUTH_REQ_GSS_CONT
#define AUTH_REQ_SCM_CREDS
#define AUTH_REQ_SASL_FIN
void initPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
#define PQExpBufferDataBroken(buf)
#define SCRAM_SHA_256_PLUS_NAME
#define SCRAM_SHA_256_NAME
const pg_fe_sasl_mech * sasl
PQExpBufferData errorMessage
bool(* channel_bound)(void *state)
void *(* init)(PGconn *conn, const char *password, const char *mech)
void(* exchange)(void *state, char *input, int inputlen, char **output, int *outputlen, bool *done, bool *success)