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, bool *async)
 
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

PQauthDataHook_type PQauthDataHook
 
const pg_fe_sasl_mech pg_scram_mech
 

Function Documentation

◆ pg_fe_getauthname()

char * pg_fe_getauthname ( PQExpBuffer  errorMessage)

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

1345{
1346#ifdef WIN32
1347 return pg_fe_getusername(0, errorMessage);
1348#else
1349 return pg_fe_getusername(geteuid(), errorMessage);
1350#endif
1351}
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
Definition: fe-auth.c:1286

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

1287{
1288 char *result = NULL;
1289 const char *name = NULL;
1290
1291#ifdef WIN32
1292 /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1293 char username[256 + 1];
1294 DWORD namesize = sizeof(username);
1295#else
1296 struct passwd pwbuf;
1297 struct passwd *pw = NULL;
1298 char buf[1024];
1299 int rc;
1300#endif
1301
1302#ifdef WIN32
1303 if (GetUserName(username, &namesize))
1304 name = username;
1305 else if (errorMessage)
1306 libpq_append_error(errorMessage,
1307 "user name lookup failure: error code %lu",
1308 GetLastError());
1309#else
1310 rc = getpwuid_r(user_id, &pwbuf, buf, sizeof buf, &pw);
1311 if (rc != 0)
1312 {
1313 errno = rc;
1314 if (errorMessage)
1315 libpq_append_error(errorMessage, "could not look up local user ID %ld: %m", (long) user_id);
1316 }
1317 else if (!pw)
1318 {
1319 if (errorMessage)
1320 libpq_append_error(errorMessage, "local user with ID %ld does not exist", (long) user_id);
1321 }
1322 else
1323 name = pw->pw_name;
1324#endif
1325
1326 if (name)
1327 {
1328 result = strdup(name);
1329 if (result == NULL && errorMessage)
1330 libpq_append_error(errorMessage, "out of memory");
1331 }
1332
1333 return result;
1334}
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1352
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 915 of file fe-auth-scram.c.

916{
917 char *prep_password;
919 char saltbuf[SCRAM_DEFAULT_SALT_LEN];
920 char *result;
921
922 /*
923 * Normalize the password with SASLprep. If that doesn't work, because
924 * the password isn't valid UTF-8 or contains prohibited characters, just
925 * proceed with the original password. (See comments at the top of
926 * auth-scram.c.)
927 */
928 rc = pg_saslprep(password, &prep_password);
929 if (rc == SASLPREP_OOM)
930 {
931 *errstr = libpq_gettext("out of memory");
932 return NULL;
933 }
934 if (rc == SASLPREP_SUCCESS)
935 password = (const char *) prep_password;
936
937 /* Generate a random salt */
939 {
940 *errstr = libpq_gettext("could not generate random salt");
941 free(prep_password);
942 return NULL;
943 }
944
948 errstr);
949
950 free(prep_password);
951
952 return result;
953}
@ PG_SHA256
Definition: cryptohash.h:24
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:934
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:209
#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:51
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,
bool *  async 
)

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

1067{
1068 int oldmsglen;
1069
1070 *async = false;
1071
1072 if (!check_expected_areq(areq, conn))
1073 return STATUS_ERROR;
1074
1075 switch (areq)
1076 {
1077 case AUTH_REQ_OK:
1078 break;
1079
1080 case AUTH_REQ_KRB4:
1081 libpq_append_conn_error(conn, "Kerberos 4 authentication not supported");
1082 return STATUS_ERROR;
1083
1084 case AUTH_REQ_KRB5:
1085 libpq_append_conn_error(conn, "Kerberos 5 authentication not supported");
1086 return STATUS_ERROR;
1087
1088#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
1089 case AUTH_REQ_GSS:
1090#if !defined(ENABLE_SSPI)
1091 /* no native SSPI, so use GSSAPI library for it */
1092 case AUTH_REQ_SSPI:
1093#endif
1094 {
1095 int r;
1096
1097 pglock_thread();
1098
1099 /*
1100 * If we have both GSS and SSPI support compiled in, use SSPI
1101 * support by default. This is overridable by a connection
1102 * string parameter. Note that when using SSPI we still leave
1103 * the negotiate parameter off, since we want SSPI to use the
1104 * GSSAPI kerberos protocol. For actual SSPI negotiate
1105 * protocol, we use AUTH_REQ_SSPI.
1106 */
1107#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1108 if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
1109 r = pg_GSS_startup(conn, payloadlen);
1110 else
1111 r = pg_SSPI_startup(conn, 0, payloadlen);
1112#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1113 r = pg_GSS_startup(conn, payloadlen);
1114#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1115 r = pg_SSPI_startup(conn, 0, payloadlen);
1116#endif
1117 if (r != STATUS_OK)
1118 {
1119 /* Error message already filled in. */
1121 return STATUS_ERROR;
1122 }
1124 }
1125 break;
1126
1127 case AUTH_REQ_GSS_CONT:
1128 {
1129 int r;
1130
1131 pglock_thread();
1132#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1133 if (conn->usesspi)
1134 r = pg_SSPI_continue(conn, payloadlen);
1135 else
1136 r = pg_GSS_continue(conn, payloadlen);
1137#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
1138 r = pg_GSS_continue(conn, payloadlen);
1139#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
1140 r = pg_SSPI_continue(conn, payloadlen);
1141#endif
1142 if (r != STATUS_OK)
1143 {
1144 /* Error message already filled in. */
1146 return STATUS_ERROR;
1147 }
1149 }
1150 break;
1151#else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1152 /* No GSSAPI *or* SSPI support */
1153 case AUTH_REQ_GSS:
1154 case AUTH_REQ_GSS_CONT:
1155 libpq_append_conn_error(conn, "GSSAPI authentication not supported");
1156 return STATUS_ERROR;
1157#endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
1158
1159#ifdef ENABLE_SSPI
1160 case AUTH_REQ_SSPI:
1161
1162 /*
1163 * SSPI has its own startup message so libpq can decide which
1164 * method to use. Indicate to pg_SSPI_startup that we want SSPI
1165 * negotiation instead of Kerberos.
1166 */
1167 pglock_thread();
1168 if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
1169 {
1170 /* Error message already filled in. */
1172 return STATUS_ERROR;
1173 }
1175 break;
1176#else
1177
1178 /*
1179 * No SSPI support. However, if we have GSSAPI but not SSPI
1180 * support, AUTH_REQ_SSPI will have been handled in the codepath
1181 * for AUTH_REQ_GSS above, so don't duplicate the case label in
1182 * that case.
1183 */
1184#if !defined(ENABLE_GSS)
1185 case AUTH_REQ_SSPI:
1186 libpq_append_conn_error(conn, "SSPI authentication not supported");
1187 return STATUS_ERROR;
1188#endif /* !define(ENABLE_GSS) */
1189#endif /* ENABLE_SSPI */
1190
1191
1192 case AUTH_REQ_CRYPT:
1193 libpq_append_conn_error(conn, "Crypt authentication not supported");
1194 return STATUS_ERROR;
1195
1196 case AUTH_REQ_MD5:
1197 case AUTH_REQ_PASSWORD:
1198 {
1199 char *password;
1200
1201 conn->password_needed = true;
1203 if (password == NULL)
1204 password = conn->pgpass;
1205 if (password == NULL || password[0] == '\0')
1206 {
1209 return STATUS_ERROR;
1210 }
1212 {
1214 "fe_sendauth: error sending password authentication\n");
1215 return STATUS_ERROR;
1216 }
1217
1218 /* We expect no further authentication requests. */
1219 conn->client_finished_auth = true;
1220 break;
1221 }
1222
1223 case AUTH_REQ_SASL:
1224
1225 /*
1226 * The request contains the name (as assigned by IANA) of the
1227 * authentication mechanism.
1228 */
1229 if (pg_SASL_init(conn, payloadlen, async) != STATUS_OK)
1230 {
1231 /* pg_SASL_init already set the error message */
1232 return STATUS_ERROR;
1233 }
1234 break;
1235
1236 case AUTH_REQ_SASL_CONT:
1237 case AUTH_REQ_SASL_FIN:
1238 {
1239 bool final = false;
1240
1241 if (conn->sasl_state == NULL)
1242 {
1244 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1245 return STATUS_ERROR;
1246 }
1247 oldmsglen = conn->errorMessage.len;
1248
1249 if (areq == AUTH_REQ_SASL_FIN)
1250 final = true;
1251
1252 if (pg_SASL_continue(conn, payloadlen, final, async) != STATUS_OK)
1253 {
1254 /*
1255 * Append a generic error message unless pg_SASL_continue
1256 * did set a more specific one already.
1257 */
1258 if (conn->errorMessage.len == oldmsglen)
1260 "fe_sendauth: error in SASL authentication\n");
1261 return STATUS_ERROR;
1262 }
1263 break;
1264 }
1265
1266 default:
1267 libpq_append_conn_error(conn, "authentication method %u not supported", areq);
1268 return STATUS_ERROR;
1269 }
1270
1271 return STATUS_OK;
1272}
#define STATUS_OK
Definition: c.h:1140
#define STATUS_ERROR
Definition: c.h:1141
static bool check_expected_areq(AuthRequest areq, PGconn *conn)
Definition: fe-auth.c:903
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final, bool *async)
Definition: fe-auth.c:704
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
Definition: fe-auth.c:796
static int pg_SASL_init(PGconn *conn, int payloadlen, bool *async)
Definition: fe-auth.c:435
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1381
#define PQnoPasswordSupplied
Definition: libpq-fe.h:633
#define pglock_thread()
Definition: libpq-int.h:732
#define pgunlock_thread()
Definition: libpq-int.h:733
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:52
char * password
Definition: libpq-int.h:369
char * pgpass
Definition: libpq-int.h:401
bool client_finished_auth
Definition: libpq-int.h:521
PQExpBufferData errorMessage
Definition: libpq-int.h:671
char * gsslib
Definition: libpq-int.h:425
void * sasl_state
Definition: libpq-int.h:600
int whichhost
Definition: libpq-int.h:483
pg_conn_host * connhost
Definition: libpq-int.h:484
bool password_needed
Definition: libpq-int.h:508

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

Referenced by pg_SASL_init(), and pqConnectOptions2().

◆ PQauthDataHook

PQauthDataHook_type PQauthDataHook
extern

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

Referenced by PQgetAuthDataHook(), PQsetAuthDataHook(), prompt_user(), and setup_token_request().