33 #ifdef HAVE_SYS_UCRED_H
34 #include <sys/ucred.h>
36 #ifndef MAXHOSTNAMELEN
63 gss_flags = GSS_C_MUTUAL_FLAG;
64 gss_buffer_desc ginbuf;
65 gss_buffer_desc goutbuf;
71 if (
conn->gctx != GSS_C_NO_CONTEXT)
73 ginbuf.length = payloadlen;
74 ginbuf.value =
malloc(payloadlen);
99 conn->gcred = GSS_C_NO_CREDENTIAL;
102 gss_flags |= GSS_C_DELEG_FLAG;
104 maj_stat = gss_init_sec_context(&min_stat,
111 GSS_C_NO_CHANNEL_BINDINGS,
112 (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
120 if (goutbuf.length != 0)
128 goutbuf.value, goutbuf.length) !=
STATUS_OK)
130 gss_release_buffer(&lmin_s, &goutbuf);
134 gss_release_buffer(&lmin_s, &goutbuf);
136 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
141 gss_release_name(&lmin_s, &
conn->gtarg_nam);
143 gss_delete_sec_context(&lmin_s, &
conn->gctx, GSS_C_NO_BUFFER);
147 if (maj_stat == GSS_S_COMPLETE)
150 gss_release_name(&lmin_s, &
conn->gtarg_nam);
166 if (!(host && host[0] !=
'\0'))
186 conn->gctx = GSS_C_NO_CONTEXT;
188 return pg_GSS_continue(
conn, payloadlen);
199 pg_SSPI_error(
PGconn *
conn,
const char *mprefix, SECURITY_STATUS r)
203 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
204 FORMAT_MESSAGE_FROM_SYSTEM,
206 sysmsg,
sizeof(sysmsg), NULL) == 0)
208 mprefix, (
unsigned int) r);
211 mprefix, sysmsg, (
unsigned int) r);
218 pg_SSPI_continue(
PGconn *
conn,
int payloadlen)
221 CtxtHandle newContext;
224 SecBufferDesc outbuf;
225 SecBuffer OutBuffers[1];
226 SecBuffer InBuffers[1];
227 char *inputbuf = NULL;
229 if (
conn->sspictx != NULL)
235 inputbuf =
malloc(payloadlen);
252 inbuf.ulVersion = SECBUFFER_VERSION;
254 inbuf.pBuffers = InBuffers;
255 InBuffers[0].pvBuffer = inputbuf;
256 InBuffers[0].cbBuffer = payloadlen;
257 InBuffers[0].BufferType = SECBUFFER_TOKEN;
260 OutBuffers[0].pvBuffer = NULL;
261 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
262 OutBuffers[0].cbBuffer = 0;
264 outbuf.pBuffers = OutBuffers;
265 outbuf.ulVersion = SECBUFFER_VERSION;
267 r = InitializeSecurityContext(
conn->sspicred,
270 ISC_REQ_ALLOCATE_MEMORY,
272 SECURITY_NETWORK_DREP,
273 (
conn->sspictx == NULL) ? NULL : &inbuf,
283 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
290 if (
conn->sspictx == NULL)
294 if (
conn->sspictx == NULL)
299 memcpy(
conn->sspictx, &newContext,
sizeof(CtxtHandle));
306 if (outbuf.cBuffers > 0)
308 if (outbuf.cBuffers != 1)
316 "SSPI returned invalid number of output buffers\n");
325 if (outbuf.pBuffers[0].cbBuffer > 0)
328 outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
330 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
334 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
351 pg_SSPI_startup(
PGconn *
conn,
int use_negotiate,
int payloadlen)
367 if (
conn->sspicred == NULL)
373 r = AcquireCredentialsHandle(NULL,
374 use_negotiate ?
"negotiate" :
"kerberos",
375 SECPKG_CRED_OUTBOUND,
386 conn->sspicred = NULL;
395 if (!(host && host[0] !=
'\0'))
401 if (!
conn->sspitarget)
414 return pg_SSPI_continue(
conn, payloadlen);
424 char *initialresponse = NULL;
425 int initialresponselen;
428 const char *selected_mechanism;
453 selected_mechanism = NULL;
459 "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
466 if (mechanism_buf.
data[0] ==
'\0')
529 if (!selected_mechanism)
538 libpq_append_conn_error(
conn,
"channel binding is required, but server did not offer an authentication method that supports channel binding");
580 &initialresponse, &initialresponselen,
606 free(initialresponse);
612 free(initialresponse);
617 free(initialresponse);
638 challenge =
malloc(payloadlen + 1);
652 challenge[payloadlen] =
'\0';
655 challenge, payloadlen,
673 if (
output == NULL && !done)
705 char *crypt_pwd = NULL;
706 const char *pwd_to_send;
723 const char *errstr = NULL;
743 4, crypt_pwd, &errstr))
750 pwd_to_send = crypt_pwd;
773 return libpq_gettext(
"server requested a cleartext password");
778 return libpq_gettext(
"server requested GSSAPI authentication");
780 return libpq_gettext(
"server requested SSPI authentication");
784 return libpq_gettext(
"server requested SASL authentication");
787 return libpq_gettext(
"server requested an unknown authentication type");
794 #define auth_method_allowed(conn, type) \
795 (((conn)->allowed_auth_methods & (1 << (type))) != 0)
806 const char *reason = NULL;
809 "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask");
879 reason =
libpq_gettext(
"server did not complete authentication");
982 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
984 #if !defined(ENABLE_SSPI)
1001 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1003 r = pg_GSS_startup(
conn, payloadlen);
1005 r = pg_SSPI_startup(
conn, 0, payloadlen);
1006 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1007 r = pg_GSS_startup(
conn, payloadlen);
1008 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1009 r = pg_SSPI_startup(
conn, 0, payloadlen);
1026 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1028 r = pg_SSPI_continue(
conn, payloadlen);
1030 r = pg_GSS_continue(
conn, payloadlen);
1031 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1032 r = pg_GSS_continue(
conn, payloadlen);
1033 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1034 r = pg_SSPI_continue(
conn, payloadlen);
1078 #if !defined(ENABLE_GSS)
1108 "fe_sendauth: error sending password authentication\n");
1135 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1145 "fe_sendauth: error in SASL authentication\n");
1172 char *result = NULL;
1173 const char *
name = NULL;
1180 char pwdbuf[BUFSIZ];
1184 if (GetUserName(
username, &namesize))
1186 else if (errorMessage)
1188 "user name lookup failure: error code %lu",
1193 else if (errorMessage)
1199 result = strdup(
name);
1200 if (result == NULL && errorMessage)
1237 const char *errstr = NULL;
1278 const char *algorithm)
1280 #define MAX_ALGORITHM_NAME_LEN 50
1282 char *crypt_pwd = NULL;
1290 if (algorithm == NULL)
1321 strcpy(algobuf,
val);
1324 algorithm = algobuf;
1332 if (strcmp(algorithm,
"on") == 0 ||
1333 strcmp(algorithm,
"off") == 0)
1339 if (strcmp(algorithm,
"scram-sha-256") == 0)
1341 const char *errstr = NULL;
1349 else if (strcmp(algorithm,
"md5") == 0)
1354 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
const pg_fe_sasl_mech pg_scram_mech
char * pg_fe_scram_build_secret(const char *password, int iterations, const char **errstr)
#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)
bool pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
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)
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 AUTH_REQ_SASL_CONT
#define PqMsg_SASLInitialResponse
#define AUTH_REQ_PASSWORD
#define AUTH_REQ_GSS_CONT
#define AUTH_REQ_SASL_FIN
#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
int scram_sha_256_iterations
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)