PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 1255 of file fe-auth.c.

1256 {
1257 #ifdef WIN32
1258  return pg_fe_getusername(0, errorMessage);
1259 #else
1260  return pg_fe_getusername(geteuid(), errorMessage);
1261 #endif
1262 }
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
Definition: fe-auth.c:1197

References pg_fe_getusername().

Referenced by conninfo_add_defaults(), and pqConnectOptions2().

◆ pg_fe_getusername()

char* pg_fe_getusername ( uid_t  user_id,
PQExpBuffer  errorMessage 
)

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

1198 {
1199  char *result = NULL;
1200  const char *name = NULL;
1201 
1202 #ifdef WIN32
1203  /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1204  char username[256 + 1];
1205  DWORD namesize = sizeof(username);
1206 #else
1207  struct passwd pwbuf;
1208  struct passwd *pw = NULL;
1209  char buf[1024];
1210  int rc;
1211 #endif
1212 
1213 #ifdef WIN32
1214  if (GetUserName(username, &namesize))
1215  name = username;
1216  else if (errorMessage)
1217  libpq_append_error(errorMessage,
1218  "user name lookup failure: error code %lu",
1219  GetLastError());
1220 #else
1221  rc = getpwuid_r(user_id, &pwbuf, buf, sizeof buf, &pw);
1222  if (rc != 0)
1223  {
1224  errno = rc;
1225  if (errorMessage)
1226  libpq_append_error(errorMessage, "could not look up local user ID %ld: %m", (long) user_id);
1227  }
1228  else if (!pw)
1229  {
1230  if (errorMessage)
1231  libpq_append_error(errorMessage, "local user with ID %ld does not exist", (long) user_id);
1232  }
1233  else
1234  name = pw->pw_name;
1235 #endif
1236 
1237  if (name)
1238  {
1239  result = strdup(name);
1240  if (result == NULL && errorMessage)
1241  libpq_append_error(errorMessage, "out of memory");
1242  }
1243 
1244  return result;
1245 }
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1343
static char * username
Definition: initdb.c:153
static char * buf
Definition: pg_test_fsync.c:72
const char * name

References buf, libpq_append_error(), name, 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 892 of file fe-auth-scram.c.

893 {
894  char *prep_password;
895  pg_saslprep_rc rc;
896  char saltbuf[SCRAM_DEFAULT_SALT_LEN];
897  char *result;
898 
899  /*
900  * Normalize the password with SASLprep. If that doesn't work, because
901  * the password isn't valid UTF-8 or contains prohibited characters, just
902  * proceed with the original password. (See comments at the top of
903  * auth-scram.c.)
904  */
905  rc = pg_saslprep(password, &prep_password);
906  if (rc == SASLPREP_OOM)
907  {
908  *errstr = libpq_gettext("out of memory");
909  return NULL;
910  }
911  if (rc == SASLPREP_SUCCESS)
912  password = (const char *) prep_password;
913 
914  /* Generate a random salt */
916  {
917  *errstr = libpq_gettext("could not generate random salt");
918  free(prep_password);
919  return NULL;
920  }
921 
925  errstr);
926 
927  free(prep_password);
928 
929  return result;
930 }
@ PG_SHA256
Definition: cryptohash.h:24
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:906
bool pg_strong_random(void *buf, size_t len)
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1047
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:210
#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:52
int iterations
Definition: thread-thread.c:39

References free, iterations, 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 989 of file fe-auth.c.

990 {
991  int oldmsglen;
992 
993  if (!check_expected_areq(areq, conn))
994  return STATUS_ERROR;
995 
996  switch (areq)
997  {
998  case AUTH_REQ_OK:
999  break;
1000 
1001  case AUTH_REQ_KRB4:
1002  libpq_append_conn_error(conn, "Kerberos 4 authentication not supported");
1003  return STATUS_ERROR;
1004 
1005  case AUTH_REQ_KRB5:
1006  libpq_append_conn_error(conn, "Kerberos 5 authentication not supported");
1007  return STATUS_ERROR;
1008 
1009 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
1010  case AUTH_REQ_GSS:
1011 #if !defined(ENABLE_SSPI)
1012  /* no native SSPI, so use GSSAPI library for it */
1013  case AUTH_REQ_SSPI:
1014 #endif
1015  {
1016  int r;
1017 
1018  pglock_thread();
1019 
1020  /*
1021  * If we have both GSS and SSPI support compiled in, use SSPI
1022  * support by default. This is overridable by a connection
1023  * string parameter. Note that when using SSPI we still leave
1024  * the negotiate parameter off, since we want SSPI to use the
1025  * GSSAPI kerberos protocol. For actual SSPI negotiate
1026  * protocol, we use AUTH_REQ_SSPI.
1027  */
1028 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1029  if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
1030  r = pg_GSS_startup(conn, payloadlen);
1031  else
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);
1037 #endif
1038  if (r != STATUS_OK)
1039  {
1040  /* Error message already filled in. */
1041  pgunlock_thread();
1042  return STATUS_ERROR;
1043  }
1044  pgunlock_thread();
1045  }
1046  break;
1047 
1048  case AUTH_REQ_GSS_CONT:
1049  {
1050  int r;
1051 
1052  pglock_thread();
1053 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1054  if (conn->usesspi)
1055  r = pg_SSPI_continue(conn, payloadlen);
1056  else
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);
1062 #endif
1063  if (r != STATUS_OK)
1064  {
1065  /* Error message already filled in. */
1066  pgunlock_thread();
1067  return STATUS_ERROR;
1068  }
1069  pgunlock_thread();
1070  }
1071  break;
1072 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1073  /* No GSSAPI *or* SSPI support */
1074  case AUTH_REQ_GSS:
1075  case AUTH_REQ_GSS_CONT:
1076  libpq_append_conn_error(conn, "GSSAPI authentication not supported");
1077  return STATUS_ERROR;
1078 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1079 
1080 #ifdef ENABLE_SSPI
1081  case AUTH_REQ_SSPI:
1082 
1083  /*
1084  * SSPI has its own startup message so libpq can decide which
1085  * method to use. Indicate to pg_SSPI_startup that we want SSPI
1086  * negotiation instead of Kerberos.
1087  */
1088  pglock_thread();
1089  if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
1090  {
1091  /* Error message already filled in. */
1092  pgunlock_thread();
1093  return STATUS_ERROR;
1094  }
1095  pgunlock_thread();
1096  break;
1097 #else
1098 
1099  /*
1100  * No SSPI support. However, if we have GSSAPI but not SSPI
1101  * support, AUTH_REQ_SSPI will have been handled in the codepath
1102  * for AUTH_REQ_GSS above, so don't duplicate the case label in
1103  * that case.
1104  */
1105 #if !defined(ENABLE_GSS)
1106  case AUTH_REQ_SSPI:
1107  libpq_append_conn_error(conn, "SSPI authentication not supported");
1108  return STATUS_ERROR;
1109 #endif /* !define(ENABLE_GSS) */
1110 #endif /* ENABLE_SSPI */
1111 
1112 
1113  case AUTH_REQ_CRYPT:
1114  libpq_append_conn_error(conn, "Crypt authentication not supported");
1115  return STATUS_ERROR;
1116 
1117  case AUTH_REQ_MD5:
1118  case AUTH_REQ_PASSWORD:
1119  {
1120  char *password;
1121 
1122  conn->password_needed = true;
1124  if (password == NULL)
1125  password = conn->pgpass;
1126  if (password == NULL || password[0] == '\0')
1127  {
1130  return STATUS_ERROR;
1131  }
1133  {
1135  "fe_sendauth: error sending password authentication\n");
1136  return STATUS_ERROR;
1137  }
1138 
1139  /* We expect no further authentication requests. */
1140  conn->client_finished_auth = true;
1141  break;
1142  }
1143 
1144  case AUTH_REQ_SASL:
1145 
1146  /*
1147  * The request contains the name (as assigned by IANA) of the
1148  * authentication mechanism.
1149  */
1150  if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
1151  {
1152  /* pg_SASL_init already set the error message */
1153  return STATUS_ERROR;
1154  }
1155  break;
1156 
1157  case AUTH_REQ_SASL_CONT:
1158  case AUTH_REQ_SASL_FIN:
1159  if (conn->sasl_state == NULL)
1160  {
1162  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1163  return STATUS_ERROR;
1164  }
1165  oldmsglen = conn->errorMessage.len;
1166  if (pg_SASL_continue(conn, payloadlen,
1167  (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
1168  {
1169  /* Use this message if pg_SASL_continue didn't supply one */
1170  if (conn->errorMessage.len == oldmsglen)
1172  "fe_sendauth: error in SASL authentication\n");
1173  return STATUS_ERROR;
1174  }
1175  break;
1176 
1177  default:
1178  libpq_append_conn_error(conn, "authentication method %u not supported", areq);
1179  return STATUS_ERROR;
1180  }
1181 
1182  return STATUS_OK;
1183 }
#define STATUS_OK
Definition: c.h:1174
#define STATUS_ERROR
Definition: c.h:1175
static bool check_expected_areq(AuthRequest areq, PGconn *conn)
Definition: fe-auth.c:830
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
Definition: fe-auth.c:645
static int pg_SASL_init(PGconn *conn, int payloadlen)
Definition: fe-auth.c:433
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:723
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1372
#define PQnoPasswordSupplied
Definition: libpq-fe.h:621
#define pglock_thread()
Definition: libpq-int.h:704
#define pgunlock_thread()
Definition: libpq-int.h:705
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
#define AUTH_REQ_SSPI
Definition: protocol.h:83
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:85
#define AUTH_REQ_GSS
Definition: protocol.h:81
#define AUTH_REQ_MD5
Definition: protocol.h:79
#define AUTH_REQ_KRB5
Definition: protocol.h:76
#define AUTH_REQ_OK
Definition: protocol.h:74
#define AUTH_REQ_KRB4
Definition: protocol.h:75
#define AUTH_REQ_PASSWORD
Definition: protocol.h:77
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:82
#define AUTH_REQ_CRYPT
Definition: protocol.h:78
#define AUTH_REQ_SASL
Definition: protocol.h:84
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86
PGconn * conn
Definition: streamutil.c:53
char * password
Definition: libpq-int.h:367
char * pgpass
Definition: libpq-int.h:398
bool client_finished_auth
Definition: libpq-int.h:503
PQExpBufferData errorMessage
Definition: libpq-int.h:643
char * gsslib
Definition: libpq-int.h:422
void * sasl_state
Definition: libpq-int.h:572
int whichhost
Definition: libpq-int.h:467
pg_conn_host * connhost
Definition: libpq-int.h:468
bool password_needed
Definition: libpq-int.h:492

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 32 of file fe-auth-scram.c.

Referenced by pg_SASL_init().