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_getauthname (PQExpBuffer errorMessage)
 
char * pg_fe_scram_build_secret (const char *password)
 

Variables

const pg_fe_sasl_mech pg_scram_mech
 

Function Documentation

◆ pg_fe_getauthname()

char* pg_fe_getauthname ( PQExpBuffer  errorMessage)

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

References appendPQExpBuffer(), appendPQExpBufferStr(), libpq_gettext, name, pglock_thread, pgunlock_thread, pqGetpwuid(), strerror_r, and username.

Referenced by connectOptions2(), and conninfo_add_defaults().

1102 {
1103  char *result = NULL;
1104  const char *name = NULL;
1105 
1106 #ifdef WIN32
1107  /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1108  char username[256 + 1];
1109  DWORD namesize = sizeof(username);
1110 #else
1111  uid_t user_id = geteuid();
1112  char pwdbuf[BUFSIZ];
1113  struct passwd pwdstr;
1114  struct passwd *pw = NULL;
1115  int pwerr;
1116 #endif
1117 
1118  /*
1119  * Some users are using configure --enable-thread-safety-force, so we
1120  * might as well do the locking within our library to protect
1121  * pqGetpwuid(). In fact, application developers can use getpwuid() in
1122  * their application if they use the locking call we provide, or install
1123  * their own locking function using PQregisterThreadLock().
1124  */
1125  pglock_thread();
1126 
1127 #ifdef WIN32
1128  if (GetUserName(username, &namesize))
1129  name = username;
1130  else if (errorMessage)
1131  appendPQExpBuffer(errorMessage,
1132  libpq_gettext("user name lookup failure: error code %lu\n"),
1133  GetLastError());
1134 #else
1135  pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
1136  if (pw != NULL)
1137  name = pw->pw_name;
1138  else if (errorMessage)
1139  {
1140  if (pwerr != 0)
1141  appendPQExpBuffer(errorMessage,
1142  libpq_gettext("could not look up local user ID %d: %s\n"),
1143  (int) user_id,
1144  strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
1145  else
1146  appendPQExpBuffer(errorMessage,
1147  libpq_gettext("local user with ID %d does not exist\n"),
1148  (int) user_id);
1149  }
1150 #endif
1151 
1152  if (name)
1153  {
1154  result = strdup(name);
1155  if (result == NULL && errorMessage)
1156  appendPQExpBufferStr(errorMessage,
1157  libpq_gettext("out of memory\n"));
1158  }
1159 
1160  pgunlock_thread();
1161 
1162  return result;
1163 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define pglock_thread()
Definition: libpq-int.h:634
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
const char * username
Definition: pgbench.c:282
#define strerror_r
Definition: port.h:233
int uid_t
Definition: win32_port.h:236
const char * name
Definition: encode.c:561
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result)
Definition: thread.c:65
#define pgunlock_thread()
Definition: libpq-int.h:635
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ pg_fe_scram_build_secret()

char* pg_fe_scram_build_secret ( const char *  password)

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

References free, pg_saslprep(), pg_strong_random(), SASLPREP_OOM, SASLPREP_SUCCESS, scram_build_secret(), SCRAM_DEFAULT_ITERATIONS, and SCRAM_DEFAULT_SALT_LEN.

Referenced by PQencryptPasswordConn().

889 {
890  char *prep_password;
891  pg_saslprep_rc rc;
892  char saltbuf[SCRAM_DEFAULT_SALT_LEN];
893  char *result;
894 
895  /*
896  * Normalize the password with SASLprep. If that doesn't work, because
897  * the password isn't valid UTF-8 or contains prohibited characters, just
898  * proceed with the original password. (See comments at top of file.)
899  */
900  rc = pg_saslprep(password, &prep_password);
901  if (rc == SASLPREP_OOM)
902  return NULL;
903  if (rc == SASLPREP_SUCCESS)
904  password = (const char *) prep_password;
905 
906  /* Generate a random salt */
908  {
909  if (prep_password)
910  free(prep_password);
911  return NULL;
912  }
913 
914  result = scram_build_secret(saltbuf, SCRAM_DEFAULT_SALT_LEN,
916 
917  if (prep_password)
918  free(prep_password);
919 
920  return result;
921 }
char * scram_build_secret(const char *salt, int saltlen, int iterations, const char *password)
Definition: scram-common.c:169
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1044
pg_saslprep_rc
Definition: saslprep.h:20
static char * password
Definition: streamutil.c:53
#define SCRAM_DEFAULT_SALT_LEN
Definition: scram-common.h:41
#define free(a)
Definition: header.h:65
bool pg_strong_random(void *buf, size_t len)
#define SCRAM_DEFAULT_ITERATIONS
Definition: scram-common.h:47

◆ pg_fe_sendauth()

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

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

References appendPQExpBuffer(), 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_SCM_CREDS, AUTH_REQ_SSPI, check_expected_areq(), pg_conn::connhost, pg_conn::errorMessage, pg_conn::gsslib, PQExpBufferData::len, libpq_gettext, password, pg_conn_host::password, pg_conn::password_needed, pg_local_sendauth(), 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().

889 {
890  int oldmsglen;
891 
892  if (!check_expected_areq(areq, conn))
893  return STATUS_ERROR;
894 
895  switch (areq)
896  {
897  case AUTH_REQ_OK:
898  break;
899 
900  case AUTH_REQ_KRB4:
902  libpq_gettext("Kerberos 4 authentication not supported\n"));
903  return STATUS_ERROR;
904 
905  case AUTH_REQ_KRB5:
907  libpq_gettext("Kerberos 5 authentication not supported\n"));
908  return STATUS_ERROR;
909 
910 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
911  case AUTH_REQ_GSS:
912 #if !defined(ENABLE_SSPI)
913  /* no native SSPI, so use GSSAPI library for it */
914  case AUTH_REQ_SSPI:
915 #endif
916  {
917  int r;
918 
919  pglock_thread();
920 
921  /*
922  * If we have both GSS and SSPI support compiled in, use SSPI
923  * support by default. This is overridable by a connection
924  * string parameter. Note that when using SSPI we still leave
925  * the negotiate parameter off, since we want SSPI to use the
926  * GSSAPI kerberos protocol. For actual SSPI negotiate
927  * protocol, we use AUTH_REQ_SSPI.
928  */
929 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
930  if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
931  r = pg_GSS_startup(conn, payloadlen);
932  else
933  r = pg_SSPI_startup(conn, 0, payloadlen);
934 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
935  r = pg_GSS_startup(conn, payloadlen);
936 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
937  r = pg_SSPI_startup(conn, 0, payloadlen);
938 #endif
939  if (r != STATUS_OK)
940  {
941  /* Error message already filled in. */
942  pgunlock_thread();
943  return STATUS_ERROR;
944  }
945  pgunlock_thread();
946  }
947  break;
948 
949  case AUTH_REQ_GSS_CONT:
950  {
951  int r;
952 
953  pglock_thread();
954 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
955  if (conn->usesspi)
956  r = pg_SSPI_continue(conn, payloadlen);
957  else
958  r = pg_GSS_continue(conn, payloadlen);
959 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
960  r = pg_GSS_continue(conn, payloadlen);
961 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
962  r = pg_SSPI_continue(conn, payloadlen);
963 #endif
964  if (r != STATUS_OK)
965  {
966  /* Error message already filled in. */
967  pgunlock_thread();
968  return STATUS_ERROR;
969  }
970  pgunlock_thread();
971  }
972  break;
973 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
974  /* No GSSAPI *or* SSPI support */
975  case AUTH_REQ_GSS:
976  case AUTH_REQ_GSS_CONT:
978  libpq_gettext("GSSAPI authentication not supported\n"));
979  return STATUS_ERROR;
980 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
981 
982 #ifdef ENABLE_SSPI
983  case AUTH_REQ_SSPI:
984 
985  /*
986  * SSPI has its own startup message so libpq can decide which
987  * method to use. Indicate to pg_SSPI_startup that we want SSPI
988  * negotiation instead of Kerberos.
989  */
990  pglock_thread();
991  if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
992  {
993  /* Error message already filled in. */
994  pgunlock_thread();
995  return STATUS_ERROR;
996  }
997  pgunlock_thread();
998  break;
999 #else
1000 
1001  /*
1002  * No SSPI support. However, if we have GSSAPI but not SSPI
1003  * support, AUTH_REQ_SSPI will have been handled in the codepath
1004  * for AUTH_REQ_GSS above, so don't duplicate the case label in
1005  * that case.
1006  */
1007 #if !defined(ENABLE_GSS)
1008  case AUTH_REQ_SSPI:
1010  libpq_gettext("SSPI authentication not supported\n"));
1011  return STATUS_ERROR;
1012 #endif /* !define(ENABLE_GSS) */
1013 #endif /* ENABLE_SSPI */
1014 
1015 
1016  case AUTH_REQ_CRYPT:
1018  libpq_gettext("Crypt authentication not supported\n"));
1019  return STATUS_ERROR;
1020 
1021  case AUTH_REQ_MD5:
1022  case AUTH_REQ_PASSWORD:
1023  {
1024  char *password;
1025 
1026  conn->password_needed = true;
1027  password = conn->connhost[conn->whichhost].password;
1028  if (password == NULL)
1029  password = conn->pgpass;
1030  if (password == NULL || password[0] == '\0')
1031  {
1034  return STATUS_ERROR;
1035  }
1036  if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
1037  {
1039  "fe_sendauth: error sending password authentication\n");
1040  return STATUS_ERROR;
1041  }
1042  break;
1043  }
1044 
1045  case AUTH_REQ_SASL:
1046 
1047  /*
1048  * The request contains the name (as assigned by IANA) of the
1049  * authentication mechanism.
1050  */
1051  if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
1052  {
1053  /* pg_SASL_init already set the error message */
1054  return STATUS_ERROR;
1055  }
1056  break;
1057 
1058  case AUTH_REQ_SASL_CONT:
1059  case AUTH_REQ_SASL_FIN:
1060  if (conn->sasl_state == NULL)
1061  {
1063  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1064  return STATUS_ERROR;
1065  }
1066  oldmsglen = conn->errorMessage.len;
1067  if (pg_SASL_continue(conn, payloadlen,
1068  (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
1069  {
1070  /* Use this message if pg_SASL_continue didn't supply one */
1071  if (conn->errorMessage.len == oldmsglen)
1073  "fe_sendauth: error in SASL authentication\n");
1074  return STATUS_ERROR;
1075  }
1076  break;
1077 
1078  case AUTH_REQ_SCM_CREDS:
1079  if (pg_local_sendauth(conn) != STATUS_OK)
1080  return STATUS_ERROR;
1081  break;
1082 
1083  default:
1085  libpq_gettext("authentication method %u not supported\n"), areq);
1086  return STATUS_ERROR;
1087  }
1088 
1089  return STATUS_OK;
1090 }
#define AUTH_REQ_SSPI
Definition: pqcomm.h:160
static int pg_local_sendauth(PGconn *conn)
Definition: fe-auth.c:720
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:163
bool password_needed
Definition: libpq-int.h:451
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define AUTH_REQ_OK
Definition: pqcomm.h:151
#define AUTH_REQ_GSS
Definition: pqcomm.h:158
static int pg_SASL_init(PGconn *conn, int payloadlen)
Definition: fe-auth.c:418
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:772
#define STATUS_ERROR
Definition: c.h:1171
#define pglock_thread()
Definition: libpq-int.h:634
#define PQnoPasswordSupplied
Definition: libpq-fe.h:559
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define AUTH_REQ_MD5
Definition: pqcomm.h:156
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
Definition: fe-auth.c:634
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:427
void * sasl_state
Definition: libpq-int.h:505
static char * password
Definition: streamutil.c:53
#define AUTH_REQ_CRYPT
Definition: pqcomm.h:155
#define STATUS_OK
Definition: c.h:1170
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:154
char * gsslib
Definition: libpq-int.h:391
PQExpBufferData errorMessage
Definition: libpq-int.h:571
#define AUTH_REQ_KRB5
Definition: pqcomm.h:153
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:162
#define AUTH_REQ_KRB4
Definition: pqcomm.h:152
char * pgpass
Definition: libpq-int.h:369
#define AUTH_REQ_SASL
Definition: pqcomm.h:161
#define AUTH_REQ_GSS_CONT
Definition: pqcomm.h:159
static bool check_expected_areq(AuthRequest areq, PGconn *conn)
Definition: fe-auth.c:838
#define pgunlock_thread()
Definition: libpq-int.h:635
int whichhost
Definition: libpq-int.h:426
#define libpq_gettext(x)
Definition: libpq-int.h:841
#define AUTH_REQ_SCM_CREDS
Definition: pqcomm.h:157
char * password
Definition: libpq-int.h:338

Variable Documentation

◆ pg_scram_mech

const pg_fe_sasl_mech pg_scram_mech

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

Referenced by pg_SASL_init().