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;
426 const char *selected_mechanism;
451 selected_mechanism = NULL;
457 "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
464 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");
581 &initialresponse, &initialresponselen);
606 free(initialresponse);
612 free(initialresponse);
617 free(initialresponse);
637 challenge =
malloc(payloadlen + 1);
651 challenge[payloadlen] =
'\0';
654 challenge, payloadlen,
703 char *crypt_pwd = NULL;
704 const char *pwd_to_send;
721 const char *errstr = NULL;
741 4, crypt_pwd, &errstr))
748 pwd_to_send = crypt_pwd;
758 pwd_to_send, strlen(pwd_to_send) + 1);
772 return libpq_gettext(
"server requested a cleartext password");
777 return libpq_gettext(
"server requested GSSAPI authentication");
779 return libpq_gettext(
"server requested SSPI authentication");
783 return libpq_gettext(
"server requested SASL authentication");
786 return libpq_gettext(
"server requested an unknown authentication type");
793 #define auth_method_allowed(conn, type) \
794 (((conn)->allowed_auth_methods & (1 << (type))) != 0)
805 const char *reason = NULL;
808 "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask");
878 reason =
libpq_gettext(
"server did not complete authentication");
981 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
983 #if !defined(ENABLE_SSPI)
1000 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1002 r = pg_GSS_startup(
conn, payloadlen);
1004 r = pg_SSPI_startup(
conn, 0, payloadlen);
1005 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1006 r = pg_GSS_startup(
conn, payloadlen);
1007 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1008 r = pg_SSPI_startup(
conn, 0, payloadlen);
1025 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1027 r = pg_SSPI_continue(
conn, payloadlen);
1029 r = pg_GSS_continue(
conn, payloadlen);
1030 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1031 r = pg_GSS_continue(
conn, payloadlen);
1032 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1033 r = pg_SSPI_continue(
conn, payloadlen);
1077 #if !defined(ENABLE_GSS)
1107 "fe_sendauth: error sending password authentication\n");
1134 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1144 "fe_sendauth: error in SASL authentication\n");
1171 char *result = NULL;
1172 const char *
name = NULL;
1179 char pwdbuf[BUFSIZ];
1183 if (GetUserName(
username, &namesize))
1185 else if (errorMessage)
1187 "user name lookup failure: error code %lu",
1192 else if (errorMessage)
1198 result = strdup(
name);
1199 if (result == NULL && errorMessage)
1236 const char *errstr = NULL;
1277 const char *algorithm)
1279 #define MAX_ALGORITHM_NAME_LEN 50
1281 char *crypt_pwd = NULL;
1289 if (algorithm == NULL)
1320 strcpy(algobuf,
val);
1323 algorithm = algobuf;
1331 if (strcmp(algorithm,
"on") == 0 ||
1332 strcmp(algorithm,
"off") == 0)
1338 if (strcmp(algorithm,
"scram-sha-256") == 0)
1340 const char *errstr = NULL;
1348 else if (strcmp(algorithm,
"md5") == 0)
1353 const char *errstr = NULL;
1406 if (!encrypted_password)
1414 strlen(encrypted_password));
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
#define Assert(condition)
#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)
PGresult * PQchangePassword(PGconn *conn, const char *user, const char *passwd)
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)
void PQfreemem(void *ptr)
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
ExecStatusType PQresultStatus(const PGresult *res)
int PQntuples(const PGresult *res)
char * PQescapeLiteral(PGconn *conn, const char *str, size_t len)
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()
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 printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
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_GSSResponse
#define PqMsg_SASLResponse
#define PqMsg_SASLInitialResponse
#define AUTH_REQ_PASSWORD
#define AUTH_REQ_GSS_CONT
#define PqMsg_PasswordMessage
#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)
SASLStatus(* exchange)(void *state, char *input, int inputlen, char **output, int *outputlen)