PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 (const char *username, const char *password)
 
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, PQExpBuffer errorMessage)
 
char * pg_fe_scram_build_verifier (const char *password)
 

Function Documentation

char* pg_fe_getauthname ( PQExpBuffer  errorMessage)

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

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

Referenced by connectOptions2(), and conninfo_add_defaults().

1015 {
1016  char *result = NULL;
1017  const char *name = NULL;
1018 
1019 #ifdef WIN32
1020  /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1021  char username[256 + 1];
1022  DWORD namesize = sizeof(username);
1023 #else
1024  uid_t user_id = geteuid();
1025  char pwdbuf[BUFSIZ];
1026  struct passwd pwdstr;
1027  struct passwd *pw = NULL;
1028  int pwerr;
1029 #endif
1030 
1031  /*
1032  * Some users are using configure --enable-thread-safety-force, so we
1033  * might as well do the locking within our library to protect
1034  * pqGetpwuid(). In fact, application developers can use getpwuid() in
1035  * their application if they use the locking call we provide, or install
1036  * their own locking function using PQregisterThreadLock().
1037  */
1038  pglock_thread();
1039 
1040 #ifdef WIN32
1041  if (GetUserName(username, &namesize))
1042  name = username;
1043  else if (errorMessage)
1044  printfPQExpBuffer(errorMessage,
1045  libpq_gettext("user name lookup failure: error code %lu\n"),
1046  GetLastError());
1047 #else
1048  pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
1049  if (pw != NULL)
1050  name = pw->pw_name;
1051  else if (errorMessage)
1052  {
1053  if (pwerr != 0)
1054  printfPQExpBuffer(errorMessage,
1055  libpq_gettext("could not look up local user ID %d: %s\n"),
1056  (int) user_id,
1057  pqStrerror(pwerr, pwdbuf, sizeof(pwdbuf)));
1058  else
1059  printfPQExpBuffer(errorMessage,
1060  libpq_gettext("local user with ID %d does not exist\n"),
1061  (int) user_id);
1062  }
1063 #endif
1064 
1065  if (name)
1066  {
1067  result = strdup(name);
1068  if (result == NULL && errorMessage)
1069  printfPQExpBuffer(errorMessage,
1070  libpq_gettext("out of memory\n"));
1071  }
1072 
1073  pgunlock_thread();
1074 
1075  return result;
1076 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int uid_t
Definition: win32.h:250
char * pqStrerror(int errnum, char *strerrbuf, size_t buflen)
Definition: thread.c:61
#define pglock_thread()
Definition: libpq-int.h:562
return result
Definition: formatting.c:1632
static char * username
Definition: initdb.c:131
#define NULL
Definition: c.h:229
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:563
#define libpq_gettext(x)
Definition: libpq-int.h:683
char* pg_fe_scram_build_verifier ( const char *  password)

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

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

Referenced by PQencryptPasswordConn().

623 {
624  char *prep_password = NULL;
625  pg_saslprep_rc rc;
626  char saltbuf[SCRAM_DEFAULT_SALT_LEN];
627  char *result;
628 
629  /*
630  * Normalize the password with SASLprep. If that doesn't work, because
631  * the password isn't valid UTF-8 or contains prohibited characters, just
632  * proceed with the original password. (See comments at top of file.)
633  */
634  rc = pg_saslprep(password, &prep_password);
635  if (rc == SASLPREP_OOM)
636  return NULL;
637  if (rc == SASLPREP_SUCCESS)
638  password = (const char *) prep_password;
639 
640  /* Generate a random salt */
642  {
643  if (prep_password)
644  free(prep_password);
645  return NULL;
646  }
647 
650 
651  if (prep_password)
652  free(prep_password);
653 
654  return result;
655 }
static char password[100]
Definition: streamutil.c:41
return result
Definition: formatting.c:1632
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:32
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
#define SCRAM_DEFAULT_ITERATIONS
Definition: scram-common.h:35
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:195
void pg_fe_scram_exchange ( void *  opaq,
char *  input,
int  inputlen,
char **  output,
int *  outputlen,
bool done,
bool success,
PQExpBuffer  errorMessage 
)

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

References build_client_final_message(), build_client_first_message(), error(), FE_SCRAM_FINISHED, FE_SCRAM_INIT, FE_SCRAM_NONCE_SENT, FE_SCRAM_PROOF_SENT, libpq_gettext, NULL, 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().

159 {
160  fe_scram_state *state = (fe_scram_state *) opaq;
161 
162  *done = false;
163  *success = false;
164  *output = NULL;
165  *outputlen = 0;
166 
167  /*
168  * Check that the input length agrees with the string length of the input.
169  * We can ignore inputlen after this.
170  */
171  if (state->state != FE_SCRAM_INIT)
172  {
173  if (inputlen == 0)
174  {
175  printfPQExpBuffer(errorMessage,
176  libpq_gettext("malformed SCRAM message (empty message)\n"));
177  goto error;
178  }
179  if (inputlen != strlen(input))
180  {
181  printfPQExpBuffer(errorMessage,
182  libpq_gettext("malformed SCRAM message (length mismatch)\n"));
183  goto error;
184  }
185  }
186 
187  switch (state->state)
188  {
189  case FE_SCRAM_INIT:
190  /* Begin the SCRAM handshake, by sending client nonce */
191  *output = build_client_first_message(state, errorMessage);
192  if (*output == NULL)
193  goto error;
194 
195  *outputlen = strlen(*output);
196  *done = false;
197  state->state = FE_SCRAM_NONCE_SENT;
198  break;
199 
200  case FE_SCRAM_NONCE_SENT:
201  /* Receive salt and server nonce, send response. */
202  if (!read_server_first_message(state, input, errorMessage))
203  goto error;
204 
205  *output = build_client_final_message(state, errorMessage);
206  if (*output == NULL)
207  goto error;
208 
209  *outputlen = strlen(*output);
210  *done = false;
211  state->state = FE_SCRAM_PROOF_SENT;
212  break;
213 
214  case FE_SCRAM_PROOF_SENT:
215  /* Receive server signature */
216  if (!read_server_final_message(state, input, errorMessage))
217  goto error;
218 
219  /*
220  * Verify server signature, to make sure we're talking to the
221  * genuine server. XXX: A fake server could simply not require
222  * authentication, though. There is currently no option in libpq
223  * to reject a connection, if SCRAM authentication did not happen.
224  */
225  if (verify_server_signature(state))
226  *success = true;
227  else
228  {
229  *success = false;
230  printfPQExpBuffer(errorMessage,
231  libpq_gettext("invalid server signature\n"));
232  }
233  *done = true;
234  state->state = FE_SCRAM_FINISHED;
235  break;
236 
237  default:
238  /* shouldn't happen */
239  printfPQExpBuffer(errorMessage,
240  libpq_gettext("invalid SCRAM exchange state\n"));
241  goto error;
242  }
243  return;
244 
245 error:
246  *done = true;
247  *success = false;
248  return;
249 }
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 bool success
Definition: pg_basebackup.c:96
static bool read_server_final_message(fe_scram_state *state, char *input, PQExpBuffer errormessage)
static char * build_client_first_message(fe_scram_state *state, PQExpBuffer errormessage)
#define NULL
Definition: c.h:229
Definition: regguts.h:298
static char * build_client_final_message(fe_scram_state *state, PQExpBuffer errormessage)
static bool verify_server_signature(fe_scram_state *state)
static bool read_server_first_message(fe_scram_state *state, char *input, PQExpBuffer errormessage)
#define libpq_gettext(x)
Definition: libpq-int.h:683
fe_scram_state_enum state
Definition: fe-auth-scram.c:42
void pg_fe_scram_free ( void *  opaq)

Definition at line 122 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::server_final_message, and fe_scram_state::server_first_message.

Referenced by closePGconn().

123 {
124  fe_scram_state *state = (fe_scram_state *) opaq;
125 
126  if (state->password)
127  free(state->password);
128 
129  /* client messages */
130  if (state->client_nonce)
131  free(state->client_nonce);
132  if (state->client_first_message_bare)
136 
137  /* first message from server */
138  if (state->server_first_message)
139  free(state->server_first_message);
140  if (state->salt)
141  free(state->salt);
142  if (state->nonce)
143  free(state->nonce);
144 
145  /* final message from server */
146  if (state->server_final_message)
147  free(state->server_final_message);
148 
149  free(state);
150 }
char * client_nonce
Definition: fe-auth-scram.c:50
char * server_first_message
Definition: fe-auth-scram.c:55
char * client_final_message_without_proof
Definition: fe-auth-scram.c:52
#define free(a)
Definition: header.h:65
Definition: regguts.h:298
char * client_first_message_bare
Definition: fe-auth-scram.c:51
char * server_final_message
Definition: fe-auth-scram.c:62
void* pg_fe_scram_init ( const char *  username,
const char *  password 
)

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

References FE_SCRAM_INIT, free, malloc, NULL, fe_scram_state::password, pg_saslprep(), SASLPREP_OOM, SASLPREP_SUCCESS, fe_scram_state::state, fe_scram_state::username, and username.

Referenced by pg_SASL_init().

85 {
87  char *prep_password;
88  pg_saslprep_rc rc;
89 
90  state = (fe_scram_state *) malloc(sizeof(fe_scram_state));
91  if (!state)
92  return NULL;
93  memset(state, 0, sizeof(fe_scram_state));
94  state->state = FE_SCRAM_INIT;
95  state->username = username;
96 
97  /* Normalize the password with SASLprep, if possible */
98  rc = pg_saslprep(password, &prep_password);
99  if (rc == SASLPREP_OOM)
100  {
101  free(state);
102  return NULL;
103  }
104  if (rc != SASLPREP_SUCCESS)
105  {
106  prep_password = strdup(password);
107  if (!prep_password)
108  {
109  free(state);
110  return NULL;
111  }
112  }
113  state->password = prep_password;
114 
115  return state;
116 }
static char password[100]
Definition: streamutil.c:41
const char * username
Definition: fe-auth-scram.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
static char * username
Definition: initdb.c:131
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
Definition: regguts.h:298
fe_scram_state_enum state
Definition: fe-auth-scram.c:42
int pg_fe_sendauth ( AuthRequest  areq,
int  payloadlen,
PGconn conn 
)

Definition at line 807 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, NULL, 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().

808 {
809  switch (areq)
810  {
811  case AUTH_REQ_OK:
812  break;
813 
814  case AUTH_REQ_KRB4:
816  libpq_gettext("Kerberos 4 authentication not supported\n"));
817  return STATUS_ERROR;
818 
819  case AUTH_REQ_KRB5:
821  libpq_gettext("Kerberos 5 authentication not supported\n"));
822  return STATUS_ERROR;
823 
824 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
825  case AUTH_REQ_GSS:
826 #if !defined(ENABLE_SSPI)
827  /* no native SSPI, so use GSSAPI library for it */
828  case AUTH_REQ_SSPI:
829 #endif
830  {
831  int r;
832 
833  pglock_thread();
834 
835  /*
836  * If we have both GSS and SSPI support compiled in, use SSPI
837  * support by default. This is overridable by a connection
838  * string parameter. Note that when using SSPI we still leave
839  * the negotiate parameter off, since we want SSPI to use the
840  * GSSAPI kerberos protocol. For actual SSPI negotiate
841  * protocol, we use AUTH_REQ_SSPI.
842  */
843 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
844  if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
845  r = pg_GSS_startup(conn, payloadlen);
846  else
847  r = pg_SSPI_startup(conn, 0, payloadlen);
848 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
849  r = pg_GSS_startup(conn, payloadlen);
850 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
851  r = pg_SSPI_startup(conn, 0, payloadlen);
852 #endif
853  if (r != STATUS_OK)
854  {
855  /* Error message already filled in. */
856  pgunlock_thread();
857  return STATUS_ERROR;
858  }
859  pgunlock_thread();
860  }
861  break;
862 
863  case AUTH_REQ_GSS_CONT:
864  {
865  int r;
866 
867  pglock_thread();
868 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
869  if (conn->usesspi)
870  r = pg_SSPI_continue(conn, payloadlen);
871  else
872  r = pg_GSS_continue(conn, payloadlen);
873 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
874  r = pg_GSS_continue(conn, payloadlen);
875 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
876  r = pg_SSPI_continue(conn, payloadlen);
877 #endif
878  if (r != STATUS_OK)
879  {
880  /* Error message already filled in. */
881  pgunlock_thread();
882  return STATUS_ERROR;
883  }
884  pgunlock_thread();
885  }
886  break;
887 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
888  /* No GSSAPI *or* SSPI support */
889  case AUTH_REQ_GSS:
890  case AUTH_REQ_GSS_CONT:
892  libpq_gettext("GSSAPI authentication not supported\n"));
893  return STATUS_ERROR;
894 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
895 
896 #ifdef ENABLE_SSPI
897  case AUTH_REQ_SSPI:
898 
899  /*
900  * SSPI has it's own startup message so libpq can decide which
901  * method to use. Indicate to pg_SSPI_startup that we want SSPI
902  * negotiation instead of Kerberos.
903  */
904  pglock_thread();
905  if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
906  {
907  /* Error message already filled in. */
908  pgunlock_thread();
909  return STATUS_ERROR;
910  }
911  pgunlock_thread();
912  break;
913 #else
914 
915  /*
916  * No SSPI support. However, if we have GSSAPI but not SSPI
917  * support, AUTH_REQ_SSPI will have been handled in the codepath
918  * for AUTH_REQ_GSSAPI above, so don't duplicate the case label in
919  * that case.
920  */
921 #if !defined(ENABLE_GSS)
922  case AUTH_REQ_SSPI:
924  libpq_gettext("SSPI authentication not supported\n"));
925  return STATUS_ERROR;
926 #endif /* !define(ENABLE_GSSAPI) */
927 #endif /* ENABLE_SSPI */
928 
929 
930  case AUTH_REQ_CRYPT:
932  libpq_gettext("Crypt authentication not supported\n"));
933  return STATUS_ERROR;
934 
935  case AUTH_REQ_MD5:
936  case AUTH_REQ_PASSWORD:
937  {
938  char *password;
939 
940  conn->password_needed = true;
941  password = conn->connhost[conn->whichhost].password;
942  if (password == NULL)
943  password = conn->pgpass;
944  if (password == NULL || password[0] == '\0')
945  {
948  return STATUS_ERROR;
949  }
950  if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
951  {
953  "fe_sendauth: error sending password authentication\n");
954  return STATUS_ERROR;
955  }
956  break;
957  }
958 
959  case AUTH_REQ_SASL:
960 
961  /*
962  * The request contains the name (as assigned by IANA) of the
963  * authentication mechanism.
964  */
965  if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
966  {
967  /* pg_SASL_init already set the error message */
968  return STATUS_ERROR;
969  }
970  break;
971 
972  case AUTH_REQ_SASL_CONT:
973  case AUTH_REQ_SASL_FIN:
974  if (conn->sasl_state == NULL)
975  {
977  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
978  return STATUS_ERROR;
979  }
980  if (pg_SASL_continue(conn, payloadlen,
981  (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
982  {
983  /* Use error message, if set already */
984  if (conn->errorMessage.len == 0)
986  "fe_sendauth: error in SASL authentication\n");
987  return STATUS_ERROR;
988  }
989  break;
990 
991  case AUTH_REQ_SCM_CREDS:
992  if (pg_local_sendauth(conn) != STATUS_OK)
993  return STATUS_ERROR;
994  break;
995 
996  default:
998  libpq_gettext("authentication method %u not supported\n"), areq);
999  return STATUS_ERROR;
1000  }
1001 
1002  return STATUS_OK;
1003 }
static char password[100]
Definition: streamutil.c:41
#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:679
#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:476
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:731
#define STATUS_ERROR
Definition: c.h:976
#define pglock_thread()
Definition: libpq-int.h:562
#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:609
pg_conn_host * connhost
Definition: libpq-int.h:397
void * sasl_state
Definition: libpq-int.h:455
#define AUTH_REQ_CRYPT
Definition: pqcomm.h:169
#define STATUS_OK
Definition: c.h:975
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
PQExpBufferData errorMessage
Definition: libpq-int.h:492
#define AUTH_REQ_KRB5
Definition: pqcomm.h:167
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:176
#define NULL
Definition: c.h:229
#define AUTH_REQ_KRB4
Definition: pqcomm.h:166
char * pgpass
Definition: libpq-int.h:343
#define AUTH_REQ_SASL
Definition: pqcomm.h:175
#define AUTH_REQ_GSS_CONT
Definition: pqcomm.h:173
#define pgunlock_thread()
Definition: libpq-int.h:563
int whichhost
Definition: libpq-int.h:396
#define libpq_gettext(x)
Definition: libpq-int.h:683
#define AUTH_REQ_SCM_CREDS
Definition: pqcomm.h:171
char * password
Definition: libpq-int.h:311