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)
 
void * pg_fe_scram_init (PGconn *conn, const char *password, const char *sasl_mechanism)
 
void pg_fe_scram_free (void *opaq)
 
void pg_fe_scram_exchange (void *opaq, char *input, int inputlen, char **output, int *outputlen, bool *done, bool *success)
 
char * pg_fe_scram_build_verifier (const char *password)
 

Function Documentation

◆ pg_fe_getauthname()

char* pg_fe_getauthname ( PQExpBuffer  errorMessage)

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

References libpq_gettext, name, pglock_thread, pgunlock_thread, pqGetpwuid(), pqStrerror(), printfPQExpBuffer(), and username.

Referenced by connectOptions2(), and conninfo_add_defaults().

1044 {
1045  char *result = NULL;
1046  const char *name = NULL;
1047 
1048 #ifdef WIN32
1049  /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1050  char username[256 + 1];
1051  DWORD namesize = sizeof(username);
1052 #else
1053  uid_t user_id = geteuid();
1054  char pwdbuf[BUFSIZ];
1055  struct passwd pwdstr;
1056  struct passwd *pw = NULL;
1057  int pwerr;
1058 #endif
1059 
1060  /*
1061  * Some users are using configure --enable-thread-safety-force, so we
1062  * might as well do the locking within our library to protect
1063  * pqGetpwuid(). In fact, application developers can use getpwuid() in
1064  * their application if they use the locking call we provide, or install
1065  * their own locking function using PQregisterThreadLock().
1066  */
1067  pglock_thread();
1068 
1069 #ifdef WIN32
1070  if (GetUserName(username, &namesize))
1071  name = username;
1072  else if (errorMessage)
1073  printfPQExpBuffer(errorMessage,
1074  libpq_gettext("user name lookup failure: error code %lu\n"),
1075  GetLastError());
1076 #else
1077  pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
1078  if (pw != NULL)
1079  name = pw->pw_name;
1080  else if (errorMessage)
1081  {
1082  if (pwerr != 0)
1083  printfPQExpBuffer(errorMessage,
1084  libpq_gettext("could not look up local user ID %d: %s\n"),
1085  (int) user_id,
1086  pqStrerror(pwerr, pwdbuf, sizeof(pwdbuf)));
1087  else
1088  printfPQExpBuffer(errorMessage,
1089  libpq_gettext("local user with ID %d does not exist\n"),
1090  (int) user_id);
1091  }
1092 #endif
1093 
1094  if (name)
1095  {
1096  result = strdup(name);
1097  if (result == NULL && errorMessage)
1098  printfPQExpBuffer(errorMessage,
1099  libpq_gettext("out of memory\n"));
1100  }
1101 
1102  pgunlock_thread();
1103 
1104  return result;
1105 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * pqStrerror(int errnum, char *strerrbuf, size_t buflen)
Definition: thread.c:61
#define pglock_thread()
Definition: libpq-int.h:564
static char * username
Definition: initdb.c:132
int uid_t
Definition: win32_port.h:241
const char * name
Definition: encode.c:521
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result)
Definition: thread.c:95
#define pgunlock_thread()
Definition: libpq-int.h:565
#define libpq_gettext(x)
Definition: libpq-int.h:687

◆ pg_fe_scram_build_verifier()

char* pg_fe_scram_build_verifier ( const char *  password)

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

References free, pg_frontend_random(), pg_saslprep(), SASLPREP_OOM, SASLPREP_SUCCESS, scram_build_verifier(), SCRAM_DEFAULT_ITERATIONS, and SCRAM_DEFAULT_SALT_LEN.

Referenced by PQencryptPasswordConn().

780 {
781  char *prep_password = NULL;
782  pg_saslprep_rc rc;
783  char saltbuf[SCRAM_DEFAULT_SALT_LEN];
784  char *result;
785 
786  /*
787  * Normalize the password with SASLprep. If that doesn't work, because
788  * the password isn't valid UTF-8 or contains prohibited characters, just
789  * proceed with the original password. (See comments at top of file.)
790  */
791  rc = pg_saslprep(password, &prep_password);
792  if (rc == SASLPREP_OOM)
793  return NULL;
794  if (rc == SASLPREP_SUCCESS)
795  password = (const char *) prep_password;
796 
797  /* Generate a random salt */
799  {
800  if (prep_password)
801  free(prep_password);
802  return NULL;
803  }
804 
807 
808  if (prep_password)
809  free(prep_password);
810 
811  return result;
812 }
static char password[100]
Definition: streamutil.c:45
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1071
pg_saslprep_rc
Definition: saslprep.h:20
#define SCRAM_DEFAULT_SALT_LEN
Definition: scram-common.h:44
#define free(a)
Definition: header.h:65
#define SCRAM_DEFAULT_ITERATIONS
Definition: scram-common.h:50
static bool pg_frontend_random(char *dst, int len)
char * scram_build_verifier(const char *salt, int saltlen, int iterations, const char *password)
Definition: scram-common.c:192

◆ pg_fe_scram_exchange()

void pg_fe_scram_exchange ( void *  opaq,
char *  input,
int  inputlen,
char **  output,
int *  outputlen,
bool done,
bool success 
)

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

References build_client_final_message(), build_client_first_message(), fe_scram_state::conn, conn, error(), pg_conn::errorMessage, FE_SCRAM_FINISHED, FE_SCRAM_INIT, FE_SCRAM_NONCE_SENT, FE_SCRAM_PROOF_SENT, libpq_gettext, printfPQExpBuffer(), read_server_final_message(), read_server_first_message(), fe_scram_state::state, and verify_server_signature().

Referenced by pg_SASL_continue(), and pg_SASL_init().

171 {
172  fe_scram_state *state = (fe_scram_state *) opaq;
173  PGconn *conn = state->conn;
174 
175  *done = false;
176  *success = false;
177  *output = NULL;
178  *outputlen = 0;
179 
180  /*
181  * Check that the input length agrees with the string length of the input.
182  * We can ignore inputlen after this.
183  */
184  if (state->state != FE_SCRAM_INIT)
185  {
186  if (inputlen == 0)
187  {
189  libpq_gettext("malformed SCRAM message (empty message)\n"));
190  goto error;
191  }
192  if (inputlen != strlen(input))
193  {
195  libpq_gettext("malformed SCRAM message (length mismatch)\n"));
196  goto error;
197  }
198  }
199 
200  switch (state->state)
201  {
202  case FE_SCRAM_INIT:
203  /* Begin the SCRAM handshake, by sending client nonce */
205  if (*output == NULL)
206  goto error;
207 
208  *outputlen = strlen(*output);
209  *done = false;
210  state->state = FE_SCRAM_NONCE_SENT;
211  break;
212 
213  case FE_SCRAM_NONCE_SENT:
214  /* Receive salt and server nonce, send response. */
215  if (!read_server_first_message(state, input))
216  goto error;
217 
219  if (*output == NULL)
220  goto error;
221 
222  *outputlen = strlen(*output);
223  *done = false;
224  state->state = FE_SCRAM_PROOF_SENT;
225  break;
226 
227  case FE_SCRAM_PROOF_SENT:
228  /* Receive server signature */
229  if (!read_server_final_message(state, input))
230  goto error;
231 
232  /*
233  * Verify server signature, to make sure we're talking to the
234  * genuine server. XXX: A fake server could simply not require
235  * authentication, though. There is currently no option in libpq
236  * to reject a connection, if SCRAM authentication did not happen.
237  */
238  if (verify_server_signature(state))
239  *success = true;
240  else
241  {
242  *success = false;
244  libpq_gettext("incorrect server signature\n"));
245  }
246  *done = true;
247  state->state = FE_SCRAM_FINISHED;
248  break;
249 
250  default:
251  /* shouldn't happen */
253  libpq_gettext("invalid SCRAM exchange state\n"));
254  goto error;
255  }
256  return;
257 
258 error:
259  *done = true;
260  *success = false;
261  return;
262 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static void error(void)
Definition: sql-dyntest.c:147
static void output(uint64 loop_count)
static char * build_client_final_message(fe_scram_state *state)
PGconn * conn
Definition: streamutil.c:46
static bool read_server_final_message(fe_scram_state *state, char *input)
static bool success
Definition: pg_basebackup.c:99
PQExpBufferData errorMessage
Definition: libpq-int.h:494
Definition: regguts.h:298
static bool read_server_first_message(fe_scram_state *state, char *input)
static char * build_client_first_message(fe_scram_state *state)
static bool verify_server_signature(fe_scram_state *state)
#define libpq_gettext(x)
Definition: libpq-int.h:687
fe_scram_state_enum state
Definition: fe-auth-scram.c:42

◆ pg_fe_scram_free()

void pg_fe_scram_free ( void *  opaq)

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

References fe_scram_state::client_final_message_without_proof, fe_scram_state::client_first_message_bare, fe_scram_state::client_nonce, free, fe_scram_state::nonce, fe_scram_state::password, fe_scram_state::salt, fe_scram_state::sasl_mechanism, fe_scram_state::server_final_message, and fe_scram_state::server_first_message.

Referenced by pqDropConnection().

133 {
134  fe_scram_state *state = (fe_scram_state *) opaq;
135 
136  if (state->password)
137  free(state->password);
138  if (state->sasl_mechanism)
139  free(state->sasl_mechanism);
140 
141  /* client messages */
142  if (state->client_nonce)
143  free(state->client_nonce);
144  if (state->client_first_message_bare)
148 
149  /* first message from server */
150  if (state->server_first_message)
151  free(state->server_first_message);
152  if (state->salt)
153  free(state->salt);
154  if (state->nonce)
155  free(state->nonce);
156 
157  /* final message from server */
158  if (state->server_final_message)
159  free(state->server_final_message);
160 
161  free(state);
162 }
char * client_nonce
Definition: fe-auth-scram.c:51
char * server_first_message
Definition: fe-auth-scram.c:56
char * client_final_message_without_proof
Definition: fe-auth-scram.c:53
#define free(a)
Definition: header.h:65
Definition: regguts.h:298
char * client_first_message_bare
Definition: fe-auth-scram.c:52
char * sasl_mechanism
Definition: fe-auth-scram.c:47
char * server_final_message
Definition: fe-auth-scram.c:63

◆ pg_fe_scram_init()

void* pg_fe_scram_init ( PGconn conn,
const char *  password,
const char *  sasl_mechanism 
)

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

References Assert, fe_scram_state::conn, conn, FE_SCRAM_INIT, free, malloc, fe_scram_state::password, pg_saslprep(), fe_scram_state::sasl_mechanism, SASLPREP_OOM, SASLPREP_SUCCESS, and fe_scram_state::state.

Referenced by pg_SASL_init().

84 {
86  char *prep_password;
87  pg_saslprep_rc rc;
88 
89  Assert(sasl_mechanism != NULL);
90 
91  state = (fe_scram_state *) malloc(sizeof(fe_scram_state));
92  if (!state)
93  return NULL;
94  memset(state, 0, sizeof(fe_scram_state));
95  state->conn = conn;
96  state->state = FE_SCRAM_INIT;
97  state->sasl_mechanism = strdup(sasl_mechanism);
98 
99  if (!state->sasl_mechanism)
100  {
101  free(state);
102  return NULL;
103  }
104 
105  /* Normalize the password with SASLprep, if possible */
106  rc = pg_saslprep(password, &prep_password);
107  if (rc == SASLPREP_OOM)
108  {
109  free(state->sasl_mechanism);
110  free(state);
111  return NULL;
112  }
113  if (rc != SASLPREP_SUCCESS)
114  {
115  prep_password = strdup(password);
116  if (!prep_password)
117  {
118  free(state->sasl_mechanism);
119  free(state);
120  return NULL;
121  }
122  }
123  state->password = prep_password;
124 
125  return state;
126 }
static char password[100]
Definition: streamutil.c:45
pg_saslprep_rc pg_saslprep(const char *input, char **output)
Definition: saslprep.c:1071
#define malloc(a)
Definition: header.h:50
pg_saslprep_rc
Definition: saslprep.h:20
PGconn * conn
Definition: streamutil.c:46
#define free(a)
Definition: header.h:65
#define Assert(condition)
Definition: c.h:680
Definition: regguts.h:298
char * sasl_mechanism
Definition: fe-auth-scram.c:47
fe_scram_state_enum state
Definition: fe-auth-scram.c:42

◆ pg_fe_sendauth()

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

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

References 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, pg_conn::connhost, pg_conn::errorMessage, 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, printfPQExpBuffer(), pg_conn::sasl_state, STATUS_ERROR, STATUS_OK, and pg_conn::whichhost.

Referenced by PQconnectPoll().

837 {
838  switch (areq)
839  {
840  case AUTH_REQ_OK:
841  break;
842 
843  case AUTH_REQ_KRB4:
845  libpq_gettext("Kerberos 4 authentication not supported\n"));
846  return STATUS_ERROR;
847 
848  case AUTH_REQ_KRB5:
850  libpq_gettext("Kerberos 5 authentication not supported\n"));
851  return STATUS_ERROR;
852 
853 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
854  case AUTH_REQ_GSS:
855 #if !defined(ENABLE_SSPI)
856  /* no native SSPI, so use GSSAPI library for it */
857  case AUTH_REQ_SSPI:
858 #endif
859  {
860  int r;
861 
862  pglock_thread();
863 
864  /*
865  * If we have both GSS and SSPI support compiled in, use SSPI
866  * support by default. This is overridable by a connection
867  * string parameter. Note that when using SSPI we still leave
868  * the negotiate parameter off, since we want SSPI to use the
869  * GSSAPI kerberos protocol. For actual SSPI negotiate
870  * protocol, we use AUTH_REQ_SSPI.
871  */
872 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
873  if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
874  r = pg_GSS_startup(conn, payloadlen);
875  else
876  r = pg_SSPI_startup(conn, 0, payloadlen);
877 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
878  r = pg_GSS_startup(conn, payloadlen);
879 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
880  r = pg_SSPI_startup(conn, 0, payloadlen);
881 #endif
882  if (r != STATUS_OK)
883  {
884  /* Error message already filled in. */
885  pgunlock_thread();
886  return STATUS_ERROR;
887  }
888  pgunlock_thread();
889  }
890  break;
891 
892  case AUTH_REQ_GSS_CONT:
893  {
894  int r;
895 
896  pglock_thread();
897 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
898  if (conn->usesspi)
899  r = pg_SSPI_continue(conn, payloadlen);
900  else
901  r = pg_GSS_continue(conn, payloadlen);
902 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
903  r = pg_GSS_continue(conn, payloadlen);
904 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
905  r = pg_SSPI_continue(conn, payloadlen);
906 #endif
907  if (r != STATUS_OK)
908  {
909  /* Error message already filled in. */
910  pgunlock_thread();
911  return STATUS_ERROR;
912  }
913  pgunlock_thread();
914  }
915  break;
916 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
917  /* No GSSAPI *or* SSPI support */
918  case AUTH_REQ_GSS:
919  case AUTH_REQ_GSS_CONT:
921  libpq_gettext("GSSAPI authentication not supported\n"));
922  return STATUS_ERROR;
923 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
924 
925 #ifdef ENABLE_SSPI
926  case AUTH_REQ_SSPI:
927 
928  /*
929  * SSPI has it's own startup message so libpq can decide which
930  * method to use. Indicate to pg_SSPI_startup that we want SSPI
931  * negotiation instead of Kerberos.
932  */
933  pglock_thread();
934  if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
935  {
936  /* Error message already filled in. */
937  pgunlock_thread();
938  return STATUS_ERROR;
939  }
940  pgunlock_thread();
941  break;
942 #else
943 
944  /*
945  * No SSPI support. However, if we have GSSAPI but not SSPI
946  * support, AUTH_REQ_SSPI will have been handled in the codepath
947  * for AUTH_REQ_GSSAPI above, so don't duplicate the case label in
948  * that case.
949  */
950 #if !defined(ENABLE_GSS)
951  case AUTH_REQ_SSPI:
953  libpq_gettext("SSPI authentication not supported\n"));
954  return STATUS_ERROR;
955 #endif /* !define(ENABLE_GSSAPI) */
956 #endif /* ENABLE_SSPI */
957 
958 
959  case AUTH_REQ_CRYPT:
961  libpq_gettext("Crypt authentication not supported\n"));
962  return STATUS_ERROR;
963 
964  case AUTH_REQ_MD5:
965  case AUTH_REQ_PASSWORD:
966  {
967  char *password;
968 
969  conn->password_needed = true;
970  password = conn->connhost[conn->whichhost].password;
971  if (password == NULL)
972  password = conn->pgpass;
973  if (password == NULL || password[0] == '\0')
974  {
977  return STATUS_ERROR;
978  }
979  if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
980  {
982  "fe_sendauth: error sending password authentication\n");
983  return STATUS_ERROR;
984  }
985  break;
986  }
987 
988  case AUTH_REQ_SASL:
989 
990  /*
991  * The request contains the name (as assigned by IANA) of the
992  * authentication mechanism.
993  */
994  if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
995  {
996  /* pg_SASL_init already set the error message */
997  return STATUS_ERROR;
998  }
999  break;
1000 
1001  case AUTH_REQ_SASL_CONT:
1002  case AUTH_REQ_SASL_FIN:
1003  if (conn->sasl_state == NULL)
1004  {
1006  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1007  return STATUS_ERROR;
1008  }
1009  if (pg_SASL_continue(conn, payloadlen,
1010  (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
1011  {
1012  /* Use error message, if set already */
1013  if (conn->errorMessage.len == 0)
1015  "fe_sendauth: error in SASL authentication\n");
1016  return STATUS_ERROR;
1017  }
1018  break;
1019 
1020  case AUTH_REQ_SCM_CREDS:
1021  if (pg_local_sendauth(conn) != STATUS_OK)
1022  return STATUS_ERROR;
1023  break;
1024 
1025  default:
1027  libpq_gettext("authentication method %u not supported\n"), areq);
1028  return STATUS_ERROR;
1029  }
1030 
1031  return STATUS_OK;
1032 }
static char password[100]
Definition: streamutil.c:45
#define AUTH_REQ_SSPI
Definition: pqcomm.h:174
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static int pg_local_sendauth(PGconn *conn)
Definition: fe-auth.c:708
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:177
bool password_needed
Definition: libpq-int.h:408
#define AUTH_REQ_OK
Definition: pqcomm.h:165
#define AUTH_REQ_GSS
Definition: pqcomm.h:172
static int pg_SASL_init(PGconn *conn, int payloadlen)
Definition: fe-auth.c:486
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:760
#define STATUS_ERROR
Definition: c.h:978
#define pglock_thread()
Definition: libpq-int.h:564
#define PQnoPasswordSupplied
Definition: libpq-fe.h:512
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define AUTH_REQ_MD5
Definition: pqcomm.h:170
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
Definition: fe-auth.c:638
pg_conn_host * connhost
Definition: libpq-int.h:398
void * sasl_state
Definition: libpq-int.h:455
#define AUTH_REQ_CRYPT
Definition: pqcomm.h:169
#define STATUS_OK
Definition: c.h:977
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define AUTH_REQ_KRB5
Definition: pqcomm.h:167
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:176
#define AUTH_REQ_KRB4
Definition: pqcomm.h:166
char * pgpass
Definition: libpq-int.h:344
#define AUTH_REQ_SASL
Definition: pqcomm.h:175
#define AUTH_REQ_GSS_CONT
Definition: pqcomm.h:173
#define pgunlock_thread()
Definition: libpq-int.h:565
int whichhost
Definition: libpq-int.h:397
#define libpq_gettext(x)
Definition: libpq-int.h:687
#define AUTH_REQ_SCM_CREDS
Definition: pqcomm.h:171
char * password
Definition: libpq-int.h:312