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);
95 maj_stat = gss_init_sec_context(&min_stat,
102 GSS_C_NO_CHANNEL_BINDINGS,
103 (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
111 if (goutbuf.length != 0)
119 goutbuf.value, goutbuf.length) !=
STATUS_OK)
121 gss_release_buffer(&lmin_s, &goutbuf);
125 gss_release_buffer(&lmin_s, &goutbuf);
127 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
132 gss_release_name(&lmin_s, &
conn->gtarg_nam);
134 gss_delete_sec_context(&lmin_s, &
conn->gctx, GSS_C_NO_BUFFER);
138 if (maj_stat == GSS_S_COMPLETE)
141 gss_release_name(&lmin_s, &
conn->gtarg_nam);
156 if (!(host && host[0] !=
'\0'))
176 conn->gctx = GSS_C_NO_CONTEXT;
178 return pg_GSS_continue(
conn, payloadlen);
189 pg_SSPI_error(
PGconn *
conn,
const char *mprefix, SECURITY_STATUS r)
193 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
194 FORMAT_MESSAGE_FROM_SYSTEM,
196 sysmsg,
sizeof(sysmsg), NULL) == 0)
198 mprefix, (
unsigned int) r);
201 mprefix, sysmsg, (
unsigned int) r);
208 pg_SSPI_continue(
PGconn *
conn,
int payloadlen)
211 CtxtHandle newContext;
214 SecBufferDesc outbuf;
215 SecBuffer OutBuffers[1];
216 SecBuffer InBuffers[1];
217 char *inputbuf = NULL;
219 if (
conn->sspictx != NULL)
225 inputbuf =
malloc(payloadlen);
242 inbuf.ulVersion = SECBUFFER_VERSION;
244 inbuf.pBuffers = InBuffers;
245 InBuffers[0].pvBuffer = inputbuf;
246 InBuffers[0].cbBuffer = payloadlen;
247 InBuffers[0].BufferType = SECBUFFER_TOKEN;
250 OutBuffers[0].pvBuffer = NULL;
251 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
252 OutBuffers[0].cbBuffer = 0;
254 outbuf.pBuffers = OutBuffers;
255 outbuf.ulVersion = SECBUFFER_VERSION;
257 r = InitializeSecurityContext(
conn->sspicred,
260 ISC_REQ_ALLOCATE_MEMORY,
262 SECURITY_NETWORK_DREP,
263 (
conn->sspictx == NULL) ? NULL : &inbuf,
273 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
280 if (
conn->sspictx == NULL)
284 if (
conn->sspictx == NULL)
289 memcpy(
conn->sspictx, &newContext,
sizeof(CtxtHandle));
296 if (outbuf.cBuffers > 0)
298 if (outbuf.cBuffers != 1)
306 "SSPI returned invalid number of output buffers\n");
315 if (outbuf.pBuffers[0].cbBuffer > 0)
318 outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
320 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
324 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
341 pg_SSPI_startup(
PGconn *
conn,
int use_negotiate,
int payloadlen)
357 if (
conn->sspicred == NULL)
363 r = AcquireCredentialsHandle(NULL,
364 use_negotiate ?
"negotiate" :
"kerberos",
365 SECPKG_CRED_OUTBOUND,
376 conn->sspicred = NULL;
385 if (!(host && host[0] !=
'\0'))
391 if (!
conn->sspitarget)
404 return pg_SSPI_continue(
conn, payloadlen);
414 char *initialresponse = NULL;
415 int initialresponselen;
418 const char *selected_mechanism;
443 selected_mechanism = NULL;
449 "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
456 if (mechanism_buf.
data[0] ==
'\0')
472 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
519 if (!selected_mechanism)
528 libpq_append_conn_error(
conn,
"channel binding is required, but server did not offer an authentication method that supports channel binding");
570 &initialresponse, &initialresponselen,
596 free(initialresponse);
602 free(initialresponse);
607 free(initialresponse);
628 challenge =
malloc(payloadlen + 1);
642 challenge[payloadlen] =
'\0';
645 challenge, payloadlen,
663 if (
output == NULL && !done)
695 char *crypt_pwd = NULL;
696 const char *pwd_to_send;
713 const char *errstr = NULL;
733 4, crypt_pwd, &errstr))
740 pwd_to_send = crypt_pwd;
763 return libpq_gettext(
"server requested a cleartext password");
768 return libpq_gettext(
"server requested GSSAPI authentication");
770 return libpq_gettext(
"server requested SSPI authentication");
774 return libpq_gettext(
"server requested SASL authentication");
777 return libpq_gettext(
"server requested an unknown authentication type");
784 #define auth_method_allowed(conn, type) \
785 (((conn)->allowed_auth_methods & (1 << (type))) != 0)
796 const char *reason = NULL;
799 "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask");
850 reason =
libpq_gettext(
"server did not complete authentication");
953 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
955 #if !defined(ENABLE_SSPI)
972 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
974 r = pg_GSS_startup(
conn, payloadlen);
976 r = pg_SSPI_startup(
conn, 0, payloadlen);
977 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
978 r = pg_GSS_startup(
conn, payloadlen);
979 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
980 r = pg_SSPI_startup(
conn, 0, payloadlen);
997 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
999 r = pg_SSPI_continue(
conn, payloadlen);
1001 r = pg_GSS_continue(
conn, payloadlen);
1002 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1003 r = pg_GSS_continue(
conn, payloadlen);
1004 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1005 r = pg_SSPI_continue(
conn, payloadlen);
1049 #if !defined(ENABLE_GSS)
1079 "fe_sendauth: error sending password authentication\n");
1106 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1116 "fe_sendauth: error in SASL authentication\n");
1143 char *result = NULL;
1144 const char *
name = NULL;
1151 char pwdbuf[BUFSIZ];
1164 if (GetUserName(
username, &namesize))
1166 else if (errorMessage)
1168 "user name lookup failure: error code %lu",
1173 else if (errorMessage)
1179 result = strdup(
name);
1180 if (result == NULL && errorMessage)
1219 const char *errstr = NULL;
1260 const char *algorithm)
1262 #define MAX_ALGORITHM_NAME_LEN 50
1264 char *crypt_pwd = NULL;
1272 if (algorithm == NULL)
1303 strcpy(algobuf,
val);
1306 algorithm = algobuf;
1314 if (strcmp(algorithm,
"on") == 0 ||
1315 strcmp(algorithm,
"off") == 0)
1321 if (strcmp(algorithm,
"scram-sha-256") == 0)
1323 const char *errstr = NULL;
1329 else if (strcmp(algorithm,
"md5") == 0)
1334 const char *errstr = NULL;
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
#define StaticAssertDecl(condition, errmessage)
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)
char * pg_fe_getauthname(PQExpBuffer errorMessage)
static const char * auth_method_description(AuthRequest areq)
char * PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm)
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
#define auth_method_allowed(conn, type)
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
ExecStatusType PQresultStatus(const 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)
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
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)
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_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
bool client_finished_auth
uint32 allowed_auth_methods
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)