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, 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)
 

Function Documentation

char* pg_fe_getauthname ( PQExpBuffer  errorMessage)

Definition at line 846 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().

847 {
848  char *result = NULL;
849  const char *name = NULL;
850 
851 #ifdef WIN32
852  /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
853  char username[256 + 1];
854  DWORD namesize = sizeof(username);
855 #else
856  uid_t user_id = geteuid();
857  char pwdbuf[BUFSIZ];
858  struct passwd pwdstr;
859  struct passwd *pw = NULL;
860  int pwerr;
861 #endif
862 
863  /*
864  * Some users are using configure --enable-thread-safety-force, so we
865  * might as well do the locking within our library to protect
866  * pqGetpwuid(). In fact, application developers can use getpwuid() in
867  * their application if they use the locking call we provide, or install
868  * their own locking function using PQregisterThreadLock().
869  */
870  pglock_thread();
871 
872 #ifdef WIN32
873  if (GetUserName(username, &namesize))
874  name = username;
875  else if (errorMessage)
876  printfPQExpBuffer(errorMessage,
877  libpq_gettext("user name lookup failure: error code %lu\n"),
878  GetLastError());
879 #else
880  pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
881  if (pw != NULL)
882  name = pw->pw_name;
883  else if (errorMessage)
884  {
885  if (pwerr != 0)
886  printfPQExpBuffer(errorMessage,
887  libpq_gettext("could not look up local user ID %d: %s\n"),
888  (int) user_id,
889  pqStrerror(pwerr, pwdbuf, sizeof(pwdbuf)));
890  else
891  printfPQExpBuffer(errorMessage,
892  libpq_gettext("local user with ID %d does not exist\n"),
893  (int) user_id);
894  }
895 #endif
896 
897  if (name)
898  {
899  result = strdup(name);
900  if (result == NULL && errorMessage)
901  printfPQExpBuffer(errorMessage,
902  libpq_gettext("out of memory\n"));
903  }
904 
905  pgunlock_thread();
906 
907  return result;
908 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int uid_t
Definition: win32.h:260
char * pqStrerror(int errnum, char *strerrbuf, size_t buflen)
Definition: thread.c:61
#define pglock_thread()
Definition: libpq-int.h:571
return result
Definition: formatting.c:1618
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:572
#define libpq_gettext(x)
Definition: libpq-int.h:692
void pg_fe_scram_exchange ( void *  opaq,
char *  input,
int  inputlen,
char **  output,
int *  outputlen,
bool done,
bool success,
PQExpBuffer  errorMessage 
)

Definition at line 132 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_proof().

Referenced by pg_SASL_exchange().

135 {
136  fe_scram_state *state = (fe_scram_state *) opaq;
137 
138  *done = false;
139  *success = false;
140  *output = NULL;
141  *outputlen = 0;
142 
143  /*
144  * Check that the input length agrees with the string length of the input.
145  * We can ignore inputlen after this.
146  */
147  if (state->state != FE_SCRAM_INIT)
148  {
149  if (inputlen == 0)
150  {
151  printfPQExpBuffer(errorMessage,
152  libpq_gettext("malformed SCRAM message (empty message)\n"));
153  goto error;
154  }
155  if (inputlen != strlen(input))
156  {
157  printfPQExpBuffer(errorMessage,
158  libpq_gettext("malformed SCRAM message (length mismatch)\n"));
159  goto error;
160  }
161  }
162 
163  switch (state->state)
164  {
165  case FE_SCRAM_INIT:
166  /* Begin the SCRAM handshake, by sending client nonce */
167  *output = build_client_first_message(state, errorMessage);
168  if (*output == NULL)
169  goto error;
170 
171  *outputlen = strlen(*output);
172  *done = false;
173  state->state = FE_SCRAM_NONCE_SENT;
174  break;
175 
176  case FE_SCRAM_NONCE_SENT:
177  /* Receive salt and server nonce, send response. */
178  if (!read_server_first_message(state, input, errorMessage))
179  goto error;
180 
181  *output = build_client_final_message(state, errorMessage);
182  if (*output == NULL)
183  goto error;
184 
185  *outputlen = strlen(*output);
186  *done = false;
187  state->state = FE_SCRAM_PROOF_SENT;
188  break;
189 
190  case FE_SCRAM_PROOF_SENT:
191  /* Receive server proof */
192  if (!read_server_final_message(state, input, errorMessage))
193  goto error;
194 
195  /*
196  * Verify server proof, to make sure we're talking to the genuine
197  * server. XXX: A fake server could simply not require
198  * authentication, though. There is currently no option in libpq
199  * to reject a connection, if SCRAM authentication did not happen.
200  */
201  if (verify_server_proof(state))
202  *success = true;
203  else
204  {
205  *success = false;
206  printfPQExpBuffer(errorMessage,
207  libpq_gettext("invalid server proof\n"));
208  }
209  *done = true;
210  state->state = FE_SCRAM_FINISHED;
211  break;
212 
213  default:
214  /* shouldn't happen */
215  printfPQExpBuffer(errorMessage,
216  libpq_gettext("invalid SCRAM exchange state\n"));
217  goto error;
218  }
219  return;
220 
221 error:
222  *done = true;
223  *success = false;
224  return;
225 }
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 verify_server_proof(fe_scram_state *state)
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 read_server_first_message(fe_scram_state *state, char *input, PQExpBuffer errormessage)
#define libpq_gettext(x)
Definition: libpq-int.h:692
fe_scram_state_enum state
Definition: fe-auth-scram.c:41
void pg_fe_scram_free ( void *  opaq)

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

Referenced by closePGconn().

102 {
103  fe_scram_state *state = (fe_scram_state *) opaq;
104 
105  /* client messages */
106  if (state->client_nonce)
107  free(state->client_nonce);
108  if (state->client_first_message_bare)
112 
113  /* first message from server */
114  if (state->server_first_message)
115  free(state->server_first_message);
116  if (state->salt)
117  free(state->salt);
118  if (state->nonce)
119  free(state->nonce);
120 
121  /* final message from server */
122  if (state->server_final_message)
123  free(state->server_final_message);
124 
125  free(state);
126 }
char * client_nonce
Definition: fe-auth-scram.c:48
char * server_first_message
Definition: fe-auth-scram.c:53
char * client_final_message_without_proof
Definition: fe-auth-scram.c:50
#define free(a)
Definition: header.h:65
Definition: regguts.h:298
char * client_first_message_bare
Definition: fe-auth-scram.c:49
char * server_final_message
Definition: fe-auth-scram.c:60
void* pg_fe_scram_init ( const char *  username,
const char *  password 
)

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

References FE_SCRAM_INIT, malloc, NULL, password, fe_scram_state::password, fe_scram_state::state, fe_scram_state::username, and username.

Referenced by pg_SASL_init().

83 {
85 
86  state = (fe_scram_state *) malloc(sizeof(fe_scram_state));
87  if (!state)
88  return NULL;
89  memset(state, 0, sizeof(fe_scram_state));
90  state->state = FE_SCRAM_INIT;
91  state->username = username;
92  state->password = password;
93 
94  return state;
95 }
static char password[100]
Definition: streamutil.c:41
const char * username
Definition: fe-auth-scram.c:44
#define malloc(a)
Definition: header.h:50
static char * username
Definition: initdb.c:131
#define NULL
Definition: c.h:229
Definition: regguts.h:298
const char * password
Definition: fe-auth-scram.c:45
fe_scram_state_enum state
Definition: fe-auth-scram.c:41
int pg_fe_sendauth ( AuthRequest  areq,
PGconn conn 
)

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

References AUTH_REQ_CRYPT, AUTH_REQ_GSS, AUTH_REQ_GSS_CONT, pg_conn::auth_req_inbuf, AUTH_REQ_KRB4, AUTH_REQ_KRB5, AUTH_REQ_MD5, AUTH_REQ_OK, AUTH_REQ_PASSWORD, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, 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_exchange(), 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().

642 {
643  switch (areq)
644  {
645  case AUTH_REQ_OK:
646  break;
647 
648  case AUTH_REQ_KRB4:
650  libpq_gettext("Kerberos 4 authentication not supported\n"));
651  return STATUS_ERROR;
652 
653  case AUTH_REQ_KRB5:
655  libpq_gettext("Kerberos 5 authentication not supported\n"));
656  return STATUS_ERROR;
657 
658 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
659  case AUTH_REQ_GSS:
660 #if !defined(ENABLE_SSPI)
661  /* no native SSPI, so use GSSAPI library for it */
662  case AUTH_REQ_SSPI:
663 #endif
664  {
665  int r;
666 
667  pglock_thread();
668 
669  /*
670  * If we have both GSS and SSPI support compiled in, use SSPI
671  * support by default. This is overridable by a connection
672  * string parameter. Note that when using SSPI we still leave
673  * the negotiate parameter off, since we want SSPI to use the
674  * GSSAPI kerberos protocol. For actual SSPI negotiate
675  * protocol, we use AUTH_REQ_SSPI.
676  */
677 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
678  if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
679  r = pg_GSS_startup(conn);
680  else
681  r = pg_SSPI_startup(conn, 0);
682 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
683  r = pg_GSS_startup(conn);
684 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
685  r = pg_SSPI_startup(conn, 0);
686 #endif
687  if (r != STATUS_OK)
688  {
689  /* Error message already filled in. */
690  pgunlock_thread();
691  return STATUS_ERROR;
692  }
693  pgunlock_thread();
694  }
695  break;
696 
697  case AUTH_REQ_GSS_CONT:
698  {
699  int r;
700 
701  pglock_thread();
702 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
703  if (conn->usesspi)
704  r = pg_SSPI_continue(conn);
705  else
706  r = pg_GSS_continue(conn);
707 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
708  r = pg_GSS_continue(conn);
709 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
710  r = pg_SSPI_continue(conn);
711 #endif
712  if (r != STATUS_OK)
713  {
714  /* Error message already filled in. */
715  pgunlock_thread();
716  return STATUS_ERROR;
717  }
718  pgunlock_thread();
719  }
720  break;
721 #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
722  /* No GSSAPI *or* SSPI support */
723  case AUTH_REQ_GSS:
724  case AUTH_REQ_GSS_CONT:
726  libpq_gettext("GSSAPI authentication not supported\n"));
727  return STATUS_ERROR;
728 #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
729 
730 #ifdef ENABLE_SSPI
731  case AUTH_REQ_SSPI:
732 
733  /*
734  * SSPI has it's own startup message so libpq can decide which
735  * method to use. Indicate to pg_SSPI_startup that we want SSPI
736  * negotiation instead of Kerberos.
737  */
738  pglock_thread();
739  if (pg_SSPI_startup(conn, 1) != STATUS_OK)
740  {
741  /* Error message already filled in. */
742  pgunlock_thread();
743  return STATUS_ERROR;
744  }
745  pgunlock_thread();
746  break;
747 #else
748 
749  /*
750  * No SSPI support. However, if we have GSSAPI but not SSPI
751  * support, AUTH_REQ_SSPI will have been handled in the codepath
752  * for AUTH_REQ_GSSAPI above, so don't duplicate the case label in
753  * that case.
754  */
755 #if !defined(ENABLE_GSS)
756  case AUTH_REQ_SSPI:
758  libpq_gettext("SSPI authentication not supported\n"));
759  return STATUS_ERROR;
760 #endif /* !define(ENABLE_GSSAPI) */
761 #endif /* ENABLE_SSPI */
762 
763 
764  case AUTH_REQ_CRYPT:
766  libpq_gettext("Crypt authentication not supported\n"));
767  return STATUS_ERROR;
768 
769  case AUTH_REQ_MD5:
770  case AUTH_REQ_PASSWORD:
771  {
772  char *password;
773 
774  conn->password_needed = true;
775  password = conn->connhost[conn->whichhost].password;
776  if (password == NULL)
777  password = conn->pgpass;
778  if (password == NULL || password[0] == '\0')
779  {
782  return STATUS_ERROR;
783  }
784  if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
785  {
787  "fe_sendauth: error sending password authentication\n");
788  return STATUS_ERROR;
789  }
790  break;
791  }
792 
793  case AUTH_REQ_SASL:
794 
795  /*
796  * The request contains the name (as assigned by IANA) of the
797  * authentication mechanism.
798  */
799  if (pg_SASL_init(conn, conn->auth_req_inbuf) != STATUS_OK)
800  {
801  /* pg_SASL_init already set the error message */
802  return STATUS_ERROR;
803  }
804  /* fall through */
805 
806  case AUTH_REQ_SASL_CONT:
807  if (conn->sasl_state == NULL)
808  {
810  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
811  return STATUS_ERROR;
812  }
813  if (pg_SASL_exchange(conn) != STATUS_OK)
814  {
815  /* Use error message, if set already */
816  if (conn->errorMessage.len == 0)
818  "fe_sendauth: error in SASL authentication\n");
819  return STATUS_ERROR;
820  }
821  break;
822 
823  case AUTH_REQ_SCM_CREDS:
824  if (pg_local_sendauth(conn) != STATUS_OK)
825  return STATUS_ERROR;
826  break;
827 
828  default:
830  libpq_gettext("authentication method %u not supported\n"), areq);
831  return STATUS_ERROR;
832  }
833 
834  return STATUS_OK;
835 }
static char password[100]
Definition: streamutil.c:41
static bool pg_SASL_init(PGconn *conn, const char *auth_mechanism)
Definition: fe-auth.c:440
#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:528
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_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:580
#define STATUS_ERROR
Definition: c.h:976
#define pglock_thread()
Definition: libpq-int.h:571
#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
char * auth_req_inbuf
Definition: libpq-int.h:456
pg_conn_host * connhost
Definition: libpq-int.h:397
void * sasl_state
Definition: libpq-int.h:460
#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:501
#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
static int pg_SASL_exchange(PGconn *conn)
Definition: fe-auth.c:486
#define AUTH_REQ_GSS_CONT
Definition: pqcomm.h:173
#define pgunlock_thread()
Definition: libpq-int.h:572
int whichhost
Definition: libpq-int.h:396
#define libpq_gettext(x)
Definition: libpq-int.h:692
#define AUTH_REQ_SCM_CREDS
Definition: pqcomm.h:171
char * password
Definition: libpq-int.h:311