PostgreSQL Source Code: src/interfaces/libpq/fe-auth.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
24
25#ifdef WIN32
26#include "win32.h"
27#else
29#include <fcntl.h>
30#include <limits.h>
32#include <sys/param.h>
34#ifdef HAVE_SYS_UCRED_H
35#include <sys/ucred.h>
36#endif
37#ifndef MAXHOSTNAMELEN
38#include <netdb.h>
39#endif
40#endif
41
49
50#ifdef ENABLE_GSS
51
52
53
54
56
57
58
59
60static int
61pg_GSS_continue(PGconn *conn, int payloadlen)
62{
63 OM_uint32 maj_stat,
64 min_stat,
65 lmin_s,
66 gss_flags = GSS_C_MUTUAL_FLAG;
67 gss_buffer_desc ginbuf;
68 gss_buffer_desc goutbuf;
69
70
71
72
73
74 if (conn->gctx != GSS_C_NO_CONTEXT)
75 {
76 ginbuf.length = payloadlen;
77 ginbuf.value = malloc(payloadlen);
78 if (!ginbuf.value)
79 {
81 payloadlen);
83 }
85 {
86
87
88
89
90 free(ginbuf.value);
92 }
93 }
94 else
95 {
96 ginbuf.length = 0;
97 ginbuf.value = NULL;
98 }
99
100
103
104
106 conn->gcred = GSS_C_NO_CREDENTIAL;
107
109 gss_flags |= GSS_C_DELEG_FLAG;
110
111 maj_stat = gss_init_sec_context(&min_stat,
114 conn->gtarg_nam,
115 GSS_C_NO_OID,
116 gss_flags,
117 0,
118 GSS_C_NO_CHANNEL_BINDINGS,
119 (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
120 NULL,
121 &goutbuf,
122 NULL,
123 NULL);
124
125 free(ginbuf.value);
126
127 if (goutbuf.length != 0)
128 {
129
130
131
132
133
136 goutbuf.value, goutbuf.length) != STATUS_OK)
137 {
138 gss_release_buffer(&lmin_s, &goutbuf);
140 }
141 }
142 gss_release_buffer(&lmin_s, &goutbuf);
143
144 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
145 {
148 maj_stat, min_stat);
149 gss_release_name(&lmin_s, &conn->gtarg_nam);
150 if (conn->gctx)
151 gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
153 }
154
155 if (maj_stat == GSS_S_COMPLETE)
156 {
158 gss_release_name(&lmin_s, &conn->gtarg_nam);
160 }
161
163}
164
165
166
167
168static int
169pg_GSS_startup(PGconn *conn, int payloadlen)
170{
171 int ret;
173
174 if (!(host && host[0] != '\0'))
175 {
178 }
179
180 if (conn->gctx)
181 {
184 }
185
188 return ret;
189
190
191
192
193
194 conn->gctx = GSS_C_NO_CONTEXT;
195
196 return pg_GSS_continue(conn, payloadlen);
197}
198#endif
199
200
201#ifdef ENABLE_SSPI
202
203
204
205
206static void
207pg_SSPI_error(PGconn *conn, const char *mprefix, SECURITY_STATUS r)
208{
209 char sysmsg[256];
210
211 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
212 FORMAT_MESSAGE_FROM_SYSTEM,
213 NULL, r, 0,
214 sysmsg, sizeof(sysmsg), NULL) == 0)
216 mprefix, (unsigned int) r);
217 else
219 mprefix, sysmsg, (unsigned int) r);
220}
221
222
223
224
225static int
226pg_SSPI_continue(PGconn *conn, int payloadlen)
227{
228 SECURITY_STATUS r;
229 CtxtHandle newContext;
230 ULONG contextAttr;
231 SecBufferDesc inbuf;
232 SecBufferDesc outbuf;
233 SecBuffer OutBuffers[1];
234 SecBuffer InBuffers[1];
235 char *inputbuf = NULL;
236
237 if (conn->sspictx != NULL)
238 {
239
240
241
242
243 inputbuf = malloc(payloadlen);
244 if (!inputbuf)
245 {
247 payloadlen);
249 }
251 {
252
253
254
255
256 free(inputbuf);
258 }
259
260 inbuf.ulVersion = SECBUFFER_VERSION;
261 inbuf.cBuffers = 1;
262 inbuf.pBuffers = InBuffers;
263 InBuffers[0].pvBuffer = inputbuf;
264 InBuffers[0].cbBuffer = payloadlen;
265 InBuffers[0].BufferType = SECBUFFER_TOKEN;
266 }
267
268
271
272 OutBuffers[0].pvBuffer = NULL;
273 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
274 OutBuffers[0].cbBuffer = 0;
275 outbuf.cBuffers = 1;
276 outbuf.pBuffers = OutBuffers;
277 outbuf.ulVersion = SECBUFFER_VERSION;
278
279 r = InitializeSecurityContext(conn->sspicred,
280 conn->sspictx,
281 conn->sspitarget,
282 ISC_REQ_ALLOCATE_MEMORY,
283 0,
284 SECURITY_NETWORK_DREP,
285 (conn->sspictx == NULL) ? NULL : &inbuf,
286 0,
287 &newContext,
288 &outbuf,
289 &contextAttr,
290 NULL);
291
292
293 free(inputbuf);
294
295 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
296 {
297 pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r);
298
300 }
301
302 if (conn->sspictx == NULL)
303 {
304
305 conn->sspictx = malloc(sizeof(CtxtHandle));
306 if (conn->sspictx == NULL)
307 {
310 }
311 memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
312 }
313
314
315
316
317
318 if (outbuf.cBuffers > 0)
319 {
320 if (outbuf.cBuffers != 1)
321 {
322
323
324
325
326
328 "SSPI returned invalid number of output buffers\n");
330 }
331
332
333
334
335
336
337 if (outbuf.pBuffers[0].cbBuffer > 0)
338 {
341 outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
342 {
343 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
345 }
346 }
347 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
348 }
349
350 if (r == SEC_E_OK)
352
353
355}
356
357
358
359
360
361
362
363static int
364pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen)
365{
366 SECURITY_STATUS r;
367 TimeStamp expire;
369
370 if (conn->sspictx)
371 {
374 }
375
376
377
378
379 conn->sspicred = malloc(sizeof(CredHandle));
380 if (conn->sspicred == NULL)
381 {
384 }
385
386 r = AcquireCredentialsHandle(NULL,
387 use_negotiate ? "negotiate" : "kerberos",
388 SECPKG_CRED_OUTBOUND,
389 NULL,
390 NULL,
391 NULL,
392 NULL,
393 conn->sspicred,
394 &expire);
395 if (r != SEC_E_OK)
396 {
397 pg_SSPI_error(conn, libpq_gettext("could not acquire SSPI credentials"), r);
399 conn->sspicred = NULL;
401 }
402
403
404
405
406
407
408 if (!(host && host[0] != '\0'))
409 {
412 }
414 if (->sspitarget)
415 {
418 }
420
421
422
423
424
425 conn->usesspi = 1;
426
427 return pg_SSPI_continue(conn, payloadlen);
428}
429#endif
430
431
432
433
434static int
436{
437 char *initialresponse = NULL;
438 int initialresponselen;
439 const char *selected_mechanism;
443
445
448 {
451 }
452
454 {
457 }
458
459
460
461
462
463
464 selected_mechanism = NULL;
465 for (;;)
466 {
468 {
470 "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
472 }
474 goto oom_error;
475
476
477 if (mechanism_buf.data[0] == '\0')
478 break;
479
480
481
482
483
484
485
486
488 {
490 {
491
492
493#ifdef USE_SSL
494
495
496
497
499 {
503 }
504#else
505
506
507
508
509
510
512 {
515 }
516#endif
517 }
518 else
519 {
520
521
522
523
524
525
526
527
528
529 libpq_append_conn_error(conn, "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection");
531 }
532 }
534 !selected_mechanism)
535 {
539 }
541 !selected_mechanism)
542 {
546 }
547 }
548
549 if (!selected_mechanism)
550 {
553 }
554
555
557 {
558 bool allowed = false;
559
561 {
563 {
564 allowed = true;
565 break;
566 }
567 }
568
569 if (!allowed)
570 {
571 libpq_append_conn_error(conn, "authentication method requirement \"%s\" failed: server requested %s authentication",
574 }
575 }
576
579 {
580 libpq_append_conn_error(conn, "channel binding is required, but server did not offer an authentication method that supports channel binding");
582 }
583
584
585
586
587
588
589
590
591
592
594 {
599 {
603 }
604 }
605
606
609
611
613 {
614
615
616
617
618
619
622 selected_mechanism);
624 goto oom_error;
625 }
626 else
627 {
628
629
630
631
634 }
635
636
638 NULL, -1,
639 &initialresponse, &initialresponselen);
640
643
645 {
646
647
648
649
650
651
652
655
656 *async = true;
658 }
659
660
661
662
665 if (pqPuts(selected_mechanism, conn))
667 if (initialresponse)
668 {
671 if (pqPutnchar(initialresponse, initialresponselen, conn))
673 }
677
680
682 free(initialresponse);
683
685
688 free(initialresponse);
690
691oom_error:
693 free(initialresponse);
696}
697
698
699
700
701
702
703static int
705{
707 int outputlen;
708 int res;
709 char *challenge;
711
712
713 challenge = malloc(payloadlen + 1);
714 if (!challenge)
715 {
717 payloadlen);
719 }
720
722 {
723 free(challenge);
725 }
726
727
730
731
732 challenge[payloadlen] = '\0';
733
735 challenge, payloadlen,
736 &output, &outputlen);
737 free(challenge);
738
740 {
741
742
743
744
745 *async = true;
746
747
748
749
750
751 }
752
754 {
755 if (outputlen != 0)
757
758 libpq_append_conn_error(conn, "AuthenticationSASLFinal received from server, but SASL authentication was not completed");
760 }
761
762
763
764
765
767 {
770 }
771
772
773
774
775
777 {
778
779
780
784
787 }
788
791
793}
794
795static int
797{
798 int ret;
799 char *crypt_pwd = NULL;
800 const char *pwd_to_send;
801 uint8 md5Salt[4];
802
803
805 {
808 }
809
810
813
814
815
816 switch (areq)
817 {
819 {
820 char *crypt_pwd2;
821 const char *errstr = NULL;
822
823
825 if (!crypt_pwd)
826 {
829 }
830
834 &errstr))
835 {
837 free(crypt_pwd);
839 }
840 if ((crypt_pwd2 + strlen("md5"), md5Salt,
841 4, crypt_pwd, &errstr))
842 {
844 free(crypt_pwd);
846 }
847
848 pwd_to_send = crypt_pwd;
849 break;
850 }
853 break;
854 default:
856 }
859 pwd_to_send, strlen(pwd_to_send) + 1);
860 free(crypt_pwd);
861 return ret;
862}
863
864
865
866
867static const char *
869{
870 switch (areq)
871 {
873 return libpq_gettext("server requested a cleartext password");
875 return libpq_gettext("server requested a hashed password");
878 return libpq_gettext("server requested GSSAPI authentication");
880 return libpq_gettext("server requested SSPI authentication");
884 return libpq_gettext("server requested SASL authentication");
885 }
886
887 return libpq_gettext("server requested an unknown authentication type");
888}
889
890
891
892
893
894#define auth_method_allowed(conn, type) \
895 (((conn)->allowed_auth_methods & (1 << (type))) != 0)
896
897
898
899
900
901
902static bool
904{
905 bool result = true;
906 const char *reason = NULL;
907
909 "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask");
910
913 {
914
915
916
917
919 {
921 return false;
922 }
924 {
926 return false;
927 }
928 }
929
930
931
932
933
934
936 {
937 switch (areq)
938 {
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
956 break;
957
958
959
960
961
962
963
964
965#ifdef ENABLE_GSS
967 {
968
969
970
971
972
973
974
975 }
976 else
977#endif
978 {
979 reason = libpq_gettext("server did not complete authentication");
980 result = false;
981 }
982
983 break;
984
993
994
995
996
997
998
1000 break;
1001
1002 default:
1003 result = false;
1004 break;
1005 }
1006 }
1007
1008 if (!result)
1009 {
1010 if (!reason)
1012
1015 return result;
1016 }
1017
1018
1019
1020
1021
1022
1023
1024
1026 {
1027 switch (areq)
1028 {
1032 break;
1035 {
1036 libpq_append_conn_error(conn, "channel binding required, but server authenticated client without channel binding");
1037 result = false;
1038 }
1039 break;
1040 default:
1041 libpq_append_conn_error(conn, "channel binding required but not supported by server's authentication request");
1042 result = false;
1043 break;
1044 }
1045 }
1046
1047 return result;
1048}
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065int
1067{
1068 int oldmsglen;
1069
1070 *async = false;
1071
1074
1075 switch (areq)
1076 {
1078 break;
1079
1083
1087
1088#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
1090#if !defined(ENABLE_SSPI)
1091
1093#endif
1094 {
1095 int r;
1096
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
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
1118 {
1119
1122 }
1124 }
1125 break;
1126
1128 {
1129 int r;
1130
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
1143 {
1144
1147 }
1149 }
1150 break;
1151#else
1152
1157#endif
1158
1159#ifdef ENABLE_SSPI
1161
1162
1163
1164
1165
1166
1168 if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
1169 {
1170
1173 }
1175 break;
1176#else
1177
1178
1179
1180
1181
1182
1183
1184#if !defined(ENABLE_GSS)
1188#endif
1189#endif
1190
1191
1195
1198 {
1200
1206 {
1210 }
1212 {
1214 "fe_sendauth: error sending password authentication\n");
1216 }
1217
1218
1220 break;
1221 }
1222
1224
1225
1226
1227
1228
1230 {
1231
1233 }
1234 break;
1235
1238 {
1239 bool final = false;
1240
1242 {
1244 "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
1246 }
1248
1250 final = true;
1251
1253 {
1254
1255
1256
1257
1260 "fe_sendauth: error in SASL authentication\n");
1262 }
1263 break;
1264 }
1265
1266 default:
1269 }
1270
1272}
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285char *
1287{
1288 char *result = NULL;
1289 const char *name = NULL;
1290
1291#ifdef WIN32
1292
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))
1305 else if (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
1327 {
1328 result = strdup(name);
1329 if (result == NULL && errorMessage)
1331 }
1332
1333 return result;
1334}
1335
1336
1337
1338
1339
1340
1341
1342
1343char *
1345{
1346#ifdef WIN32
1348#else
1350#endif
1351}
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362char *
1364{
1365 char *crypt_pwd;
1366 const char *errstr = NULL;
1367
1369 if (!crypt_pwd)
1370 return NULL;
1371
1373 {
1374 free(crypt_pwd);
1375 return NULL;
1376 }
1377
1378 return crypt_pwd;
1379}
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405char *
1407 const char *algorithm)
1408{
1409#define MAX_ALGORITHM_NAME_LEN 50
1411 char *crypt_pwd = NULL;
1412
1414 return NULL;
1415
1417
1418
1419 if (algorithm == NULL)
1420 {
1422 char *val;
1423
1424 res = PQexec(conn, "show password_encryption");
1425 if (res == NULL)
1426 {
1427
1428 return NULL;
1429 }
1431 {
1432
1434 return NULL;
1435 }
1437 {
1440 return NULL;
1441 }
1443
1445 {
1448 return NULL;
1449 }
1450 strcpy(algobuf, val);
1452
1453 algorithm = algobuf;
1454 }
1455
1456
1457
1458
1459
1460
1461 if (strcmp(algorithm, "on") == 0 ||
1462 strcmp(algorithm, "off") == 0)
1463 algorithm = "md5";
1464
1465
1466
1467
1468 if (strcmp(algorithm, "scram-sha-256") == 0)
1469 {
1470 const char *errstr = NULL;
1471
1474 &errstr);
1475 if (!crypt_pwd)
1477 }
1478 else if (strcmp(algorithm, "md5") == 0)
1479 {
1481 if (crypt_pwd)
1482 {
1483 const char *errstr = NULL;
1484
1486 {
1488 free(crypt_pwd);
1489 crypt_pwd = NULL;
1490 }
1491 }
1492 else
1494 }
1495 else
1496 {
1498 algorithm);
1499 return NULL;
1500 }
1501
1502 return crypt_pwd;
1503}
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1532{
1534 user, NULL);
1535
1536 if (!encrypted_password)
1537 {
1538
1539 return NULL;
1540 }
1541 else
1542 {
1544 strlen(encrypted_password));
1545
1546
1548
1549 if (!fmtpw)
1550 {
1551
1552 return NULL;
1553 }
1554 else
1555 {
1557
1558 if (!fmtuser)
1559 {
1560
1562 return NULL;
1563 }
1564 else
1565 {
1568
1571 fmtuser, fmtpw);
1572
1574
1575
1579
1580 return res;
1581 }
1582 }
1583 }
1584}
1585
1587
1590{
1592}
1593
1594void
1596{
1598}
1599
1600int
1602{
1603 return 0;
1604}
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
#define StaticAssertDecl(condition, errmessage)
const pg_fe_sasl_mech pg_oauth_mech
const pg_fe_sasl_mech pg_scram_mech
char * pg_fe_scram_build_secret(const char *password, int iterations, const char **errstr)
char * PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm)
#define MAX_ALGORITHM_NAME_LEN
static bool check_expected_areq(AuthRequest areq, PGconn *conn)
void PQsetAuthDataHook(PQauthDataHook_type hook)
PGresult * PQchangePassword(PGconn *conn, const char *user, const char *passwd)
PQauthDataHook_type PQauthDataHook
static int pg_SASL_continue(PGconn *conn, int payloadlen, bool final, bool *async)
static int pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
PQauthDataHook_type PQgetAuthDataHook(void)
int PQdefaultAuthDataHook(PGauthData type, PGconn *conn, void *data)
static int pg_SASL_init(PGconn *conn, int payloadlen, bool *async)
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn, bool *async)
char * pg_fe_getauthname(PQExpBuffer errorMessage)
char * PQencryptPassword(const char *passwd, const char *user)
static const char * auth_method_description(AuthRequest areq)
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
#define auth_method_allowed(conn, type)
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
void PQfreemem(void *ptr)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
ExecStatusType PQresultStatus(const PGresult *res)
void PQclear(PGresult *res)
int PQntuples(const PGresult *res)
char * PQescapeLiteral(PGconn *conn, const char *str, size_t len)
PGresult * PQexec(PGconn *conn, const char *query)
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
int PQnfields(const PGresult *res)
int pg_GSS_load_servicename(PGconn *conn)
bool pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
int pqPutInt(int value, size_t bytes, PGconn *conn)
int pqFlush(PGconn *conn)
int pqPutMsgStart(char msg_type, PGconn *conn)
int pqGets(PQExpBuffer buf, PGconn *conn)
int pqPutnchar(const void *s, size_t len, PGconn *conn)
int pqPuts(const char *s, PGconn *conn)
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
int pqGetnchar(void *s, size_t len, PGconn *conn)
int pqPutMsgEnd(PGconn *conn)
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Assert(PointerIsAligned(start, uint64))
int(* PQauthDataHook_type)(PGauthData type, PGconn *conn, void *data)
#define PQnoPasswordSupplied
#define AUTH_RESPONSE_PASSWORD
#define AUTH_RESPONSE_SASL
#define AUTH_RESPONSE_SASL_INITIAL
#define pqClearConnErrorState(conn)
#define AUTH_RESPONSE_GSS
bool pg_md5_encrypt(const char *passwd, const uint8 *salt, size_t salt_len, char *buf, const char **errstr)
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
#define pgunlock_thread()
int pg_strcasecmp(const char *s1, const char *s2)
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void initPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
#define PQExpBufferDataBroken(buf)
#define AUTH_REQ_SASL_CONT
#define PqMsg_GSSResponse
#define PqMsg_SASLResponse
#define PqMsg_SASLInitialResponse
#define AUTH_REQ_PASSWORD
#define AUTH_REQ_GSS_CONT
#define PqMsg_PasswordMessage
#define AUTH_REQ_SASL_FIN
#define SCRAM_SHA_256_PLUS_NAME
#define SCRAM_SHA_256_NAME
uint8 * scram_client_key_binary
char current_auth_response
const pg_fe_sasl_mech * sasl
void(* cleanup_async_auth)(PGconn *conn)
bool client_finished_auth
uint32 allowed_auth_methods
PQExpBufferData errorMessage
PostgresPollingStatusType(* async_auth)(PGconn *conn)
int scram_sha_256_iterations
const pg_fe_sasl_mech * allowed_sasl_mechs[2]
bool(* channel_bound)(void *state)
SASLStatus(* exchange)(void *state, bool final, char *input, int inputlen, char **output, int *outputlen)
void *(* init)(PGconn *conn, const char *password, const char *mech)