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 (conn->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 (pg\_md5\_encrypt(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)