PostgreSQL Source Code  git master
fe-auth.h File Reference
#include "libpq-fe.h"
#include "libpq-int.h"
Include dependency graph for fe-auth.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int pg_fe_sendauth (AuthRequest areq, int payloadlen, PGconn *conn)
 
char * pg_fe_getusername (uid_t user_id, PQExpBuffer errorMessage)
 
char * pg_fe_getauthname (PQExpBuffer errorMessage)
 
char * pg_fe_scram_build_secret (const char *password, int iterations, const char **errstr)
 

Variables

const pg_fe_sasl_mech pg_scram_mech
 

Function Documentation

◆ pg_fe_getauthname()

char* pg_fe_getauthname ( PQExpBuffer  errorMessage)

Definition at line 1216 of file fe-auth.c.

1217 {
1218 #ifdef WIN32
1219  return pg_fe_getusername(0, errorMessage);
1220 #else
1221  return pg_fe_getusername(geteuid(), errorMessage);
1222 #endif
1223 }
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
Definition: fe-auth.c:1160

References pg_fe_getusername().

Referenced by connectOptions2(), and conninfo_add_defaults().

◆ pg_fe_getusername()

char* pg_fe_getusername ( uid_t  user_id,
PQExpBuffer  errorMessage 
)

Definition at line 1160 of file fe-auth.c.

1161 {
1162  char *result = NULL;
1163  const char *name = NULL;
1164 
1165 #ifdef WIN32
1166  /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1167  char username[256 + 1];
1168  DWORD namesize = sizeof(username);
1169 #else
1170  char pwdbuf[BUFSIZ];
1171 #endif
1172 
1173  /*
1174  * Some users are using configure --enable-thread-safety-force, so we
1175  * might as well do the locking within our library to protect getpwuid().
1176  * In fact, application developers can use getpwuid() in their application
1177  * if they use the locking call we provide, or install their own locking
1178  * function using PQregisterThreadLock().
1179  */
1180  pglock_thread();
1181 
1182 #ifdef WIN32
1183  if (GetUserName(username, &namesize))
1184  name = username;
1185  else if (errorMessage)
1186  libpq_append_error(errorMessage,
1187  "user name lookup failure: error code %lu",
1188  GetLastError());
1189 #else
1190  if (pg_get_user_name(user_id, pwdbuf, sizeof(pwdbuf)))
1191  name = pwdbuf;
1192  else if (errorMessage)
1193  appendPQExpBuffer(errorMessage, "%s\n", pwdbuf);
1194 #endif
1195 
1196  if (name)
1197  {
1198  result = strdup(name);
1199  if (result == NULL && errorMessage)
1200  libpq_append_error(errorMessage, "out of memory");
1201  }
1202 
1203  pgunlock_thread();
1204 
1205  return result;
1206 }
const char * name
Definition: encode.c:571
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1283
#define pglock_thread()
Definition: libpq-int.h:688
#define pgunlock_thread()
Definition: libpq-int.h:689
const char * username
Definition: pgbench.c:306
bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen)
Definition: thread.c:35
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265

References appendPQExpBuffer(), libpq_append_error(), name, pg_get_user_name(), pglock_thread, pgunlock_thread, and username.

Referenced by pg_fe_getauthname(), and PQconnectPoll().

◆ pg_fe_scram_build_secret()

char* pg_fe_scram_build_secret ( const char *  password,
int  iterations,
const char **  errstr 
)

Definition at line 898 of file fe-auth-scram.c.

899 {
900  char *prep_password;
901  pg_saslprep_rc rc;
902  char saltbuf[SCRAM_DEFAULT_SALT_LEN];
903  char *result;
904 
905  /*
906  * Normalize the password with SASLprep. If that doesn't work, because
907  * the password isn't valid UTF-8 or contains prohibited characters, just
908  * proceed with the original password. (See comments at the top of
909  * auth-scram.c.)
910  */
911  rc = pg_saslprep(password, &prep_password);
912  if (rc == SASLPREP_OOM)
913  {
914  *errstr = libpq_gettext("out of memory");
915  return NULL;
916  }
917  if (rc == SASLPREP_SUCCESS)
918  password = (const char *) prep_password;
919 
920  /* Generate a random salt */
922  {
923  *errstr = libpq_gettext("could not generate random salt");
924  free(prep_password);
925  return NULL;
926  }
927 
930  iterations, password,
931  errstr);
932 
933  free(prep_password);
934 
935  return result;
936 }
@ PG_SHA256
Definition: cryptohash.h:24
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:911
bool pg_strong_random(void *buf, size_t len)
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1044
pg_saslprep_rc
Definition: saslprep.h:21
@ SASLPREP_OOM
Definition: saslprep.h:23
@ SASLPREP_SUCCESS
Definition: saslprep.h:22
char * scram_build_secret(pg_cryptohash_type hash_type, int key_length, const char *salt, int saltlen, int iterations, const char *password, const char **errstr)
Definition: scram-common.c:199
#define SCRAM_DEFAULT_SALT_LEN
Definition: scram-common.h:44
#define SCRAM_SHA_256_KEY_LEN
Definition: scram-common.h:24
static char * password
Definition: streamutil.c:53

References free, libpq_gettext, password, pg_saslprep(), PG_SHA256, pg_strong_random(), SASLPREP_OOM, SASLPREP_SUCCESS, scram_build_secret(), SCRAM_DEFAULT_SALT_LEN, and SCRAM_SHA_256_KEY_LEN.

Referenced by PQencryptPasswordConn().

◆ pg_fe_sendauth()

int pg_fe_sendauth ( AuthRequest  areq,
int  payloadlen,
PGconn conn 
)

Definition at line 952 of file fe-auth.c.

953 {
954  int oldmsglen;
955 
956  if (!check_expected_areq(areq, conn))
957  return STATUS_ERROR;
958 
959  switch (areq)
960  {
961  case AUTH_REQ_OK:
962  break;
963 
964  case AUTH_REQ_KRB4:
965  libpq_append_conn_error(conn, "Kerberos 4 authentication not supported");
966  return STATUS_ERROR;
967 
968  case AUTH_REQ_KRB5:
969  libpq_append_conn_error(conn, "Kerberos 5 authentication not supported");
970  return STATUS_ERROR;
971 
972 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
973  case AUTH_REQ_GSS:
974 #if !defined(ENABLE_SSPI)
975  /* no native SSPI, so use GSSAPI library for it */
976  case AUTH_REQ_SSPI:
977 #endif
978  {
979  int r;
980 
981  pglock_thread();
982 
983  /*
984  * If we have both GSS and SSPI support compiled in, use SSPI
985  * support by default. This is overridable by a connection
986  * string parameter. Note that when using SSPI we still leave
987  * the negotiate parameter off, since we want SSPI to use the
988  * GSSAPI kerberos protocol. For actual SSPI negotiate
989  * protocol, we use AUTH_REQ_SSPI.
990  */
991 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
992  if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
993  r = pg_GSS_startup(conn, payloadlen);
994  else
995  r = pg_SSPI_startup(conn, 0, payloadlen);
996 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
997  r = pg_GSS_startup(conn, payloadlen);
998 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
999  r = pg_SSPI_startup(conn, 0, payloadlen);
1000 #endif
1001  if (r != STATUS_OK)
1002  {
1003  /* Error message already filled in. */
1004  pgunlock_thread();
1005  return STATUS_ERROR;
1006  }
1007  pgunlock_thread();
1008  }
1009  break;
1010 
1011  case AUTH_REQ_GSS_CONT:
1012  {
1013  int r;
1014 
1015  pglock_thread();
1016 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1017  if (conn->usesspi)
1018  r = pg_SSPI_continue(conn, payloadlen);
1019  else
1020  r = pg_GSS_continue(conn, payloadlen);
1021 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1022  r = pg_GSS_continue(conn, payloadlen);
1023 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1024  r = pg_SSPI_continue(conn, payloadlen);
1025 #endif
1026  if (r != STATUS_OK)
1027  {
1028  /* Error message already filled in. */
1029  pgunlock_thread();
1030  return STATUS_ERROR;
1031  }
1032  pgunlock_thread();
1033  }
1034  break;
1035 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1036  /* No GSSAPI *or* SSPI support */
1037  case AUTH_REQ_GSS:
1038  case AUTH_REQ_GSS_CONT:
1039  libpq_append_conn_error(conn, "GSSAPI authentication not supported");
1040  return STATUS_ERROR;
1041 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1042 
1043 #ifdef ENABLE_SSPI
1044  case AUTH_REQ_SSPI:
1045 
1046  /*
1047  * SSPI has its own startup message so libpq can decide which
1048  * method to use. Indicate to pg_SSPI_startup that we want SSPI
1049  * negotiation instead of Kerberos.
1050  */
1051  pglock_thread();
1052  if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
1053  {
1054  /* Error message already filled in. */
1055  pgunlock_thread();
1056  return STATUS_ERROR;
1057  }
1058  pgunlock_thread();
1059  break;
1060 #else
1061 
1062  /*
1063  * No SSPI support. However, if we have GSSAPI but not SSPI
1064  * support, AUTH_REQ_SSPI will have been handled in the codepath
1065  * for AUTH_REQ_GSS above, so don't duplicate the case label in
1066  * that case.
1067  */
1068 #if !defined(ENABLE_GSS)
1069  case AUTH_REQ_SSPI:
1070  libpq_append_conn_error(conn, "SSPI authentication not supported");
1071  return STATUS_ERROR;
1072 #endif /* !define(ENABLE_GSS) */
1073 #endif /* ENABLE_SSPI */
1074 
1075 
1076  case AUTH_REQ_CRYPT:
1077  libpq_append_conn_error(conn, "Crypt authentication not supported");
1078  return STATUS_ERROR;
1079 
1080  case AUTH_REQ_MD5:
1081  case AUTH_REQ_PASSWORD:
1082  {
1083  char *password;
1084 
1085  conn->password_needed = true;
1087  if (password == NULL)
1088  password = conn->pgpass;
1089  if (password == NULL || password[0] == '\0')
1090  {
1093  return STATUS_ERROR;
1094  }
1096  {
1098  "fe_sendauth: error sending password authentication\n");
1099  return STATUS_ERROR;
1100  }
1101 
1102  /* We expect no further authentication requests. */
1103  conn->client_finished_auth = true;
1104  break;
1105  }
1106 
1107  case AUTH_REQ_SASL:
1108 
1109  /*
1110  * The request contains the name (as assigned by IANA) of the
1111  * authentication mechanism.
1112  */
1113  if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
1114  {
1115  /* pg_SASL_init already set the error message */
1116  return STATUS_ERROR;
1117  }
1118  break;
1119 
1120  case AUTH_REQ_SASL_CONT:
1121  case AUTH_REQ_SASL_FIN:
1122  if (conn->sasl_state == NULL)
1123  {
1125  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1126  return STATUS_ERROR;
1127  }
1128  oldmsglen = conn->errorMessage.len;
1129  if (pg_SASL_continue(conn, payloadlen,
1130  (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
1131  {
1132  /* Use this message if pg_SASL_continue didn't supply one */
1133  if (conn->errorMessage.len == oldmsglen)
1135  "fe_sendauth: error in SASL authentication\n");
1136  return STATUS_ERROR;
1137  }
1138  break;
1139 
1140  default:
1141  libpq_append_conn_error(conn, "authentication method %u not supported", areq);
1142  return STATUS_ERROR;
1143  }
1144 
1145  return STATUS_OK;
1146 }
#define STATUS_OK
Definition: c.h:1159
#define STATUS_ERROR
Definition: c.h:1160
static bool check_expected_areq(AuthRequest areq, PGconn *conn)
Definition: fe-auth.c:793
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
Definition: fe-auth.c:618
static int pg_SASL_init(PGconn *conn, int payloadlen)
Definition: fe-auth.c:412
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:692
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1312
#define PQnoPasswordSupplied
Definition: libpq-fe.h:561
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define AUTH_REQ_SSPI
Definition: pqcomm.h:128
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:130
#define AUTH_REQ_GSS
Definition: pqcomm.h:126
#define AUTH_REQ_MD5
Definition: pqcomm.h:124
#define AUTH_REQ_KRB5
Definition: pqcomm.h:121
#define AUTH_REQ_OK
Definition: pqcomm.h:119
#define AUTH_REQ_KRB4
Definition: pqcomm.h:120
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:122
#define AUTH_REQ_GSS_CONT
Definition: pqcomm.h:127
#define AUTH_REQ_CRYPT
Definition: pqcomm.h:123
#define AUTH_REQ_SASL
Definition: pqcomm.h:129
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
PGconn * conn
Definition: streamutil.c:54
char * password
Definition: libpq-int.h:351
char * pgpass
Definition: libpq-int.h:382
bool client_finished_auth
Definition: libpq-int.h:477
PQExpBufferData errorMessage
Definition: libpq-int.h:617
char * gsslib
Definition: libpq-int.h:405
void * sasl_state
Definition: libpq-int.h:543
int whichhost
Definition: libpq-int.h:442
pg_conn_host * connhost
Definition: libpq-int.h:443
bool password_needed
Definition: libpq-int.h:467

References appendPQExpBufferStr(), AUTH_REQ_CRYPT, AUTH_REQ_GSS, AUTH_REQ_GSS_CONT, AUTH_REQ_KRB4, AUTH_REQ_KRB5, AUTH_REQ_MD5, AUTH_REQ_OK, AUTH_REQ_PASSWORD, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, AUTH_REQ_SSPI, check_expected_areq(), pg_conn::client_finished_auth, conn, pg_conn::connhost, pg_conn::errorMessage, pg_conn::gsslib, PQExpBufferData::len, libpq_append_conn_error(), password, pg_conn_host::password, pg_conn::password_needed, pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pg_strcasecmp(), pglock_thread, pg_conn::pgpass, pgunlock_thread, PQnoPasswordSupplied, pg_conn::sasl_state, STATUS_ERROR, STATUS_OK, and pg_conn::whichhost.

Referenced by PQconnectPoll().

Variable Documentation

◆ pg_scram_mech

const pg_fe_sasl_mech pg_scram_mech
extern

Definition at line 33 of file fe-auth-scram.c.

Referenced by pg_SASL_init().