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 1024 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().

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

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:42
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 817 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().

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