34 #ifdef HAVE_SYS_UCRED_H
35 #include <sys/ucred.h>
37 #ifndef MAXHOSTNAMELEN
64 gss_flags = GSS_C_MUTUAL_FLAG;
65 gss_buffer_desc ginbuf;
66 gss_buffer_desc goutbuf;
72 if (
conn->gctx != GSS_C_NO_CONTEXT)
74 ginbuf.length = payloadlen;
75 ginbuf.value =
malloc(payloadlen);
104 conn->gcred = GSS_C_NO_CREDENTIAL;
107 gss_flags |= GSS_C_DELEG_FLAG;
109 maj_stat = gss_init_sec_context(&min_stat,
116 GSS_C_NO_CHANNEL_BINDINGS,
117 (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
125 if (goutbuf.length != 0)
134 goutbuf.value, goutbuf.length) !=
STATUS_OK)
136 gss_release_buffer(&lmin_s, &goutbuf);
140 gss_release_buffer(&lmin_s, &goutbuf);
142 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
147 gss_release_name(&lmin_s, &
conn->gtarg_nam);
149 gss_delete_sec_context(&lmin_s, &
conn->gctx, GSS_C_NO_BUFFER);
153 if (maj_stat == GSS_S_COMPLETE)
156 gss_release_name(&lmin_s, &
conn->gtarg_nam);
172 if (!(host && host[0] !=
'\0'))
192 conn->gctx = GSS_C_NO_CONTEXT;
194 return pg_GSS_continue(
conn, payloadlen);
205 pg_SSPI_error(
PGconn *
conn,
const char *mprefix, SECURITY_STATUS r)
209 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
210 FORMAT_MESSAGE_FROM_SYSTEM,
212 sysmsg,
sizeof(sysmsg), NULL) == 0)
214 mprefix, (
unsigned int) r);
217 mprefix, sysmsg, (
unsigned int) r);
224 pg_SSPI_continue(
PGconn *
conn,
int payloadlen)
227 CtxtHandle newContext;
230 SecBufferDesc outbuf;
231 SecBuffer OutBuffers[1];
232 SecBuffer InBuffers[1];
233 char *inputbuf = NULL;
235 if (
conn->sspictx != NULL)
241 inputbuf =
malloc(payloadlen);
258 inbuf.ulVersion = SECBUFFER_VERSION;
260 inbuf.pBuffers = InBuffers;
261 InBuffers[0].pvBuffer = inputbuf;
262 InBuffers[0].cbBuffer = payloadlen;
263 InBuffers[0].BufferType = SECBUFFER_TOKEN;
270 OutBuffers[0].pvBuffer = NULL;
271 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
272 OutBuffers[0].cbBuffer = 0;
274 outbuf.pBuffers = OutBuffers;
275 outbuf.ulVersion = SECBUFFER_VERSION;
277 r = InitializeSecurityContext(
conn->sspicred,
280 ISC_REQ_ALLOCATE_MEMORY,
282 SECURITY_NETWORK_DREP,
283 (
conn->sspictx == NULL) ? NULL : &inbuf,
293 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
300 if (
conn->sspictx == NULL)
304 if (
conn->sspictx == NULL)
309 memcpy(
conn->sspictx, &newContext,
sizeof(CtxtHandle));
316 if (outbuf.cBuffers > 0)
318 if (outbuf.cBuffers != 1)
326 "SSPI returned invalid number of output buffers\n");
335 if (outbuf.pBuffers[0].cbBuffer > 0)
339 outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
341 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
345 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
362 pg_SSPI_startup(
PGconn *
conn,
int use_negotiate,
int payloadlen)
378 if (
conn->sspicred == NULL)
384 r = AcquireCredentialsHandle(NULL,
385 use_negotiate ?
"negotiate" :
"kerberos",
386 SECPKG_CRED_OUTBOUND,
397 conn->sspicred = NULL;
406 if (!(host && host[0] !=
'\0'))
412 if (!
conn->sspitarget)
425 return pg_SSPI_continue(
conn, payloadlen);
435 char *initialresponse = NULL;
436 int initialresponselen;
437 const char *selected_mechanism;
462 selected_mechanism = NULL;
468 "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
475 if (mechanism_buf.
data[0] ==
'\0')
540 if (!selected_mechanism)
549 libpq_append_conn_error(
conn,
"channel binding is required, but server did not offer an authentication method that supports channel binding");
596 &initialresponse, &initialresponselen);
623 free(initialresponse);
629 free(initialresponse);
634 free(initialresponse);
654 challenge =
malloc(payloadlen + 1);
673 challenge[payloadlen] =
'\0';
676 challenge, payloadlen,
726 char *crypt_pwd = NULL;
727 const char *pwd_to_send;
748 const char *errstr = NULL;
768 4, crypt_pwd, &errstr))
775 pwd_to_send = crypt_pwd;
786 pwd_to_send, strlen(pwd_to_send) + 1);
800 return libpq_gettext(
"server requested a cleartext password");
805 return libpq_gettext(
"server requested GSSAPI authentication");
807 return libpq_gettext(
"server requested SSPI authentication");
811 return libpq_gettext(
"server requested SASL authentication");
814 return libpq_gettext(
"server requested an unknown authentication type");
821 #define auth_method_allowed(conn, type) \
822 (((conn)->allowed_auth_methods & (1 << (type))) != 0)
833 const char *reason = NULL;
836 "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask");
906 reason =
libpq_gettext(
"server did not complete authentication");
1009 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
1011 #if !defined(ENABLE_SSPI)
1028 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1030 r = pg_GSS_startup(
conn, payloadlen);
1032 r = pg_SSPI_startup(
conn, 0, payloadlen);
1033 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1034 r = pg_GSS_startup(
conn, payloadlen);
1035 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1036 r = pg_SSPI_startup(
conn, 0, payloadlen);
1053 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1055 r = pg_SSPI_continue(
conn, payloadlen);
1057 r = pg_GSS_continue(
conn, payloadlen);
1058 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1059 r = pg_GSS_continue(
conn, payloadlen);
1060 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1061 r = pg_SSPI_continue(
conn, payloadlen);
1105 #if !defined(ENABLE_GSS)
1135 "fe_sendauth: error sending password authentication\n");
1162 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1172 "fe_sendauth: error in SASL authentication\n");
1199 char *result = NULL;
1200 const char *
name = NULL;
1207 struct passwd pwbuf;
1208 struct passwd *pw = NULL;
1214 if (GetUserName(
username, &namesize))
1216 else if (errorMessage)
1218 "user name lookup failure: error code %lu",
1221 rc = getpwuid_r(user_id, &pwbuf,
buf,
sizeof buf, &pw);
1226 libpq_append_error(errorMessage,
"could not look up local user ID %ld: %m", (
long) user_id);
1231 libpq_append_error(errorMessage,
"local user with ID %ld does not exist", (
long) user_id);
1239 result = strdup(
name);
1240 if (result == NULL && errorMessage)
1277 const char *errstr = NULL;
1318 const char *algorithm)
1320 #define MAX_ALGORITHM_NAME_LEN 50
1322 char *crypt_pwd = NULL;
1330 if (algorithm == NULL)
1361 strcpy(algobuf,
val);
1364 algorithm = algobuf;
1372 if (strcmp(algorithm,
"on") == 0 ||
1373 strcmp(algorithm,
"off") == 0)
1379 if (strcmp(algorithm,
"scram-sha-256") == 0)
1381 const char *errstr = NULL;
1389 else if (strcmp(algorithm,
"md5") == 0)
1394 const char *errstr = NULL;
1447 if (!encrypted_password)
1455 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)
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
#define PQnoPasswordSupplied
#define AUTH_RESPONSE_PASSWORD
#define AUTH_RESPONSE_SASL
#define AUTH_RESPONSE_SASL_INITIAL
#define pqClearConnErrorState(conn)
#define AUTH_RESPONSE_GSS
#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)
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
char current_auth_response
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)