PostgreSQL Source Code: src/backend/libpq/auth.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

17

25

43

44

45

46

47

50

51

52

53

54

55

58

60 const char **logdetail);

61

62

63

64

65

66

67

68#define IDENT_USERNAME_MAX 512

69

70

71#define IDENT_PORT 113

72

74

75

76

77

78

79

81

82

83

84

85

86

87#ifdef USE_PAM

88#ifdef HAVE_PAM_PAM_APPL_H

89#include <pam/pam_appl.h>

90#endif

91#ifdef HAVE_SECURITY_PAM_APPL_H

92#include <security/pam_appl.h>

93#endif

94

95#define PGSQL_PAM_SERVICE "postgresql"

96

98static int pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,

99 struct pam_response **resp, void *appdata_ptr);

100

101static struct pam_conv pam_passw_conv = {

102 &pam_passwd_conv_proc,

103 NULL

104};

105

106static const char *pam_passwd = NULL;

107

108static Port *pam_port_cludge;

109

110static bool pam_no_password;

111#endif

112

113

114

115

116

117

118#ifdef USE_BSD_AUTH

119#include <bsd_auth.h>

120

121static int CheckBSDAuth(Port *port, char *user);

122#endif

123

124

125

126

127

128

129#ifdef USE_LDAP

130#ifndef WIN32

131

132#define LDAP_DEPRECATED 1

133#include <ldap.h>

134#else

135#include <winldap.h>

136

137#endif

138

139static int CheckLDAPAuth(Port *port);

140

141

142#ifndef LDAP_OPT_DIAGNOSTIC_MESSAGE

143#define LDAP_OPT_DIAGNOSTIC_MESSAGE LDAP_OPT_ERROR_STRING

144#endif

145

146

147static char *dummy_ldap_password_mutator(char *input);

149

150#endif

151

152

153

154

155

156#ifdef USE_SSL

157static int CheckCertAuth(Port *port);

158#endif

159

160

161

162

163

164

168

169

170

171

172

173

174#ifdef ENABLE_GSS

176

177static int pg_GSS_checkauth(Port *port);

178static int pg_GSS_recvauth(Port *port);

179#endif

180

181

182

183

184

185

186#ifdef ENABLE_SSPI

187typedef SECURITY_STATUS

188 (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (PCtxtHandle, void **);

189static int pg_SSPI_recvauth(Port *port);

190static int pg_SSPI_make_upn(char *accountname,

191 size_t accountnamesize,

192 char *domainname,

193 size_t domainnamesize,

194 bool update_accountname);

195#endif

196

197

198

199

200

202static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd);

203

204

205

206

207

208

209

210

211

212

213

214

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230static void

232{

233 const char *errstr;

234 char *cdetail;

235 int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;

236

237

238

239

240

241

242

243

244

245

246

249

250 switch (port->hba->auth_method)

251 {

254 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");

255 break;

257 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");

258 break;

260 errstr = gettext_noop("Ident authentication failed for user \"%s\"");

261 break;

263 errstr = gettext_noop("Peer authentication failed for user \"%s\"");

264 break;

268 errstr = gettext_noop("password authentication failed for user \"%s\"");

269

271 break;

273 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");

274 break;

276 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");

277 break;

279 errstr = gettext_noop("PAM authentication failed for user \"%s\"");

280 break;

282 errstr = gettext_noop("BSD authentication failed for user \"%s\"");

283 break;

285 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");

286 break;

288 errstr = gettext_noop("certificate authentication failed for user \"%s\"");

289 break;

291 errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");

292 break;

294 errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\"");

295 break;

296 default:

297 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");

298 break;

299 }

300

301 cdetail = psprintf(_("Connection matched file \"%s\" line %d: \"%s\""),

302 port->hba->sourcefile, port->hba->linenumber,

303 port->hba->rawline);

304 if (logdetail)

305 logdetail = psprintf("%s\n%s", logdetail, cdetail);

306 else

307 logdetail = cdetail;

308

310 (errcode(errcode_return),

312 logdetail ? errdetail_log("%s", logdetail) : 0));

313

314

315}

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332void

334{

336

338 {

339

340

341

342

343

344

346 (errmsg("authentication identifier set more than once"),

347 errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",

349 }

350

353

355 {

357 errmsg("connection authenticated: identity=\"%s\" method=%s "

358 "(%s:%d)",

361 port->hba->sourcefile, port->hba->linenumber));

362 }

363}

364

365

366

367

368

369

370void

372{

374 const char *logdetail = NULL;

375

376

377

378

379

380

381

383

385

386

387

388

389

390

392 {

393

396 (errcode(ERRCODE_CONFIG_FILE_ERROR),

397 errmsg("client certificates can only be checked if a root certificate store is available")));

398

399

400

401

402

403

404

405 if (port->peer_cert_valid)

407 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),

408 errmsg("connection requires a valid client certificate")));

409 }

410

411

412

413

414 switch (port->hba->auth_method)

415 {

417

418

419

420

421

422

423

424

425

426

427

428 {

429 char hostinfo[NI_MAXHOST];

430 const char *encryption_state;

431

433 hostinfo, sizeof(hostinfo),

434 NULL, 0,

435 NI_NUMERICHOST);

436

437 encryption_state =

438#ifdef ENABLE_GSS

439 (port->gss && port->gss->enc) ? _("GSS encryption") :

440#endif

441#ifdef USE_SSL

442 port->ssl_in_use ? _("SSL encryption") :

443#endif

444 _("no encryption");

445

448 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),

449

450 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",

451 hostinfo, port->user_name,

452 encryption_state)));

453 else

455 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),

456

457 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",

458 hostinfo, port->user_name,

459 port->database_name,

460 encryption_state)));

461 break;

462 }

463

465

466

467

468

469

470

471

472

473

474 {

475 char hostinfo[NI_MAXHOST];

476 const char *encryption_state;

477

479 hostinfo, sizeof(hostinfo),

480 NULL, 0,

481 NI_NUMERICHOST);

482

483 encryption_state =

484#ifdef ENABLE_GSS

485 (port->gss && port->gss->enc) ? _("GSS encryption") :

486#endif

487#ifdef USE_SSL

488 port->ssl_in_use ? _("SSL encryption") :

489#endif

490 _("no encryption");

491

492#define HOSTNAME_LOOKUP_DETAIL(port) \

493 (port->remote_hostname ? \

494 (port->remote_hostname_resolv == +1 ? \

495 errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \

496 port->remote_hostname) : \

497 port->remote_hostname_resolv == 0 ? \

498 errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \

499 port->remote_hostname) : \

500 port->remote_hostname_resolv == -1 ? \

501 errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \

502 port->remote_hostname) : \

503 port->remote_hostname_resolv == -2 ? \

504 errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \

505 port->remote_hostname, \

506 gai_strerror(port->remote_hostname_errcode)) : \

507 0) \

508 : (port->remote_hostname_resolv == -2 ? \

509 errdetail_log("Could not resolve client IP address to a host name: %s.", \

510 gai_strerror(port->remote_hostname_errcode)) : \

511 0))

512

515 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),

516

517 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",

518 hostinfo, port->user_name,

519 encryption_state),

521 else

523 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),

524

525 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",

526 hostinfo, port->user_name,

527 port->database_name,

528 encryption_state),

530 break;

531 }

532

534#ifdef ENABLE_GSS

535

536 if (port->gss == NULL)

537 port->gss = (pg_gssinfo *)

539 sizeof(pg_gssinfo));

540 port->gss->auth = true;

541

542

543

544

545

546 if (port->gss->enc)

547 status = pg_GSS_checkauth(port);

548 else

549 {

551 status = pg_GSS_recvauth(port);

552 }

553#else

555#endif

556 break;

557

559#ifdef ENABLE_SSPI

560 if (port->gss == NULL)

561 port->gss = (pg_gssinfo *)

563 sizeof(pg_gssinfo));

565 status = pg_SSPI_recvauth(port);

566#else

568#endif

569 break;

570

573 break;

574

577 break;

578

582 break;

583

586 break;

587

589#ifdef USE_PAM

590 status = CheckPAMAuth(port, port->user_name, "");

591#else

593#endif

594 break;

595

597#ifdef USE_BSD_AUTH

598 status = CheckBSDAuth(port, port->user_name);

599#else

601#endif

602 break;

603

605#ifdef USE_LDAP

606 status = CheckLDAPAuth(port);

607#else

609#endif

610 break;

613 break;

615

618 break;

621 break;

622 }

623

626 {

627

628

629

630

631#ifdef USE_SSL

632 status = CheckCertAuth(port);

633#else

635#endif

636 }

637

641 {

642

643

644

645

646

647

649 errmsg("connection authenticated: user=\"%s\" method=%s "

650 "(%s:%d)",

652 port->hba->sourcefile, port->hba->linenumber));

653 }

654

656 (*ClientAuthentication_hook) (port, status);

657

660 else

662}

663

664

665

666

667

668void

670{

672

674

677 if (extralen > 0)

679

681

682

683

684

685

686

689

691}

692

693

694

695

696

697

698static char *

700{

702 int mtype;

703

705

706

709 {

710

711

712

713

714

715 if (mtype != EOF)

717 (errcode(ERRCODE_PROTOCOL_VIOLATION),

718 errmsg("expected password response, got message type %d",

719 mtype)));

720 return NULL;

721 }

722

725 {

726

728 return NULL;

729 }

730

731

732

733

734

735

736 if (strlen(buf.data) + 1 != buf.len)

738 (errcode(ERRCODE_PROTOCOL_VIOLATION),

739 errmsg("invalid password packet size")));

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754 if (buf.len == 1)

757 errmsg("empty password returned by client")));

758

759

760 elog(DEBUG5, "received password packet");

761

762

763

764

765

766

767 return buf.data;

768}

769

770

771

772

773

774

775

776

777

778

779static int

781{

782 char *passwd;

783 int result;

784 char *shadow_pass;

785

787

789 if (passwd == NULL)

790 return STATUS_EOF;

791

793 if (shadow_pass)

794 {

796 logdetail);

797 }

798 else

800

801 if (shadow_pass)

802 pfree(shadow_pass);

804

807

808 return result;

809}

810

811

812

813

814static int

816{

817 int auth_result;

818 char *shadow_pass;

820

822 port->hba->auth_method == uaMD5);

823

824

826

827

828

829

830

831

832

833

834

835

836 if (!shadow_pass)

838 else

840

841

842

843

844

845

846

847

848

849

850

853 else

855 logdetail);

856

857 if (shadow_pass)

858 pfree(shadow_pass);

859 else

860 {

861

862

863

864

866 }

867

870

871 return auth_result;

872}

873

874static int

876{

877 uint8 md5Salt[4];

878 char *passwd;

879 int result;

880

881

883 {

885 (errmsg("could not generate random MD5 salt")));

887 }

888

890

892 if (passwd == NULL)

893 return STATUS_EOF;

894

895 if (shadow_pass)

897 md5Salt, 4, logdetail);

898 else

900

902

903 return result;

904}

905

906

907

908

909

910

911#ifdef ENABLE_GSS

912static int

914{

915 OM_uint32 maj_stat,

916 min_stat,

917 lmin_s,

918 gflags;

919 int mtype;

921 gss_buffer_desc gbuf;

922 gss_cred_id_t delegated_creds;

923

924

925

926

927

928

930 {

932 {

933

935 (errcode(ERRCODE_OUT_OF_MEMORY),

936 errmsg("could not set environment: %m")));

937 }

938 }

939

940

941

942

943

944

945

946 port->gss->cred = GSS_C_NO_CREDENTIAL;

947

948

949

950

951 port->gss->ctx = GSS_C_NO_CONTEXT;

952

953 delegated_creds = GSS_C_NO_CREDENTIAL;

954 port->gss->delegated_creds = false;

955

956

957

958

959

960

961

962 do

963 {

965

967

970 {

971

972 if (mtype != EOF)

974 (errcode(ERRCODE_PROTOCOL_VIOLATION),

975 errmsg("expected GSS response, got message type %d",

976 mtype)));

978 }

979

980

983 {

984

987 }

988

989

990 gbuf.length = buf.len;

991 gbuf.value = buf.data;

992

993 elog(DEBUG4, "processing received GSS token of length %u",

994 (unsigned int) gbuf.length);

995

996 maj_stat = gss_accept_sec_context(&min_stat,

997 &port->gss->ctx,

998 port->gss->cred,

999 &gbuf,

1000 GSS_C_NO_CHANNEL_BINDINGS,

1001 &port->gss->name,

1002 NULL,

1003 &port->gss->outbuf,

1004 &gflags,

1005 NULL,

1007

1008

1010

1011 elog(DEBUG5, "gss_accept_sec_context major: %u, "

1012 "minor: %u, outlen: %u, outflags: %x",

1013 maj_stat, min_stat,

1014 (unsigned int) port->gss->outbuf.length, gflags);

1015

1017

1018 if (delegated_creds != GSS_C_NO_CREDENTIAL && gflags & GSS_C_DELEG_FLAG)

1019 {

1021 port->gss->delegated_creds = true;

1022 }

1023

1024 if (port->gss->outbuf.length != 0)

1025 {

1026

1027

1028

1029 elog(DEBUG4, "sending GSS response token of length %u",

1030 (unsigned int) port->gss->outbuf.length);

1031

1033 port->gss->outbuf.value, port->gss->outbuf.length);

1034

1035 gss_release_buffer(&lmin_s, &port->gss->outbuf);

1036 }

1037

1038 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)

1039 {

1040 gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);

1041 pg_GSS_error(_("accepting GSS security context failed"),

1042 maj_stat, min_stat);

1044 }

1045

1046 if (maj_stat == GSS_S_CONTINUE_NEEDED)

1047 elog(DEBUG4, "GSS continue needed");

1048

1049 } while (maj_stat == GSS_S_CONTINUE_NEEDED);

1050

1051 if (port->gss->cred != GSS_C_NO_CREDENTIAL)

1052 {

1053

1054

1055

1056 gss_release_cred(&min_stat, &port->gss->cred);

1057 }

1058 return pg_GSS_checkauth(port);

1059}

1060

1061

1062

1063

1064

1065static int

1067{

1068 int ret;

1069 OM_uint32 maj_stat,

1070 min_stat,

1071 lmin_s;

1072 gss_buffer_desc gbuf;

1073 char *princ;

1074

1075

1076

1077

1078

1079 maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);

1080 if (maj_stat != GSS_S_COMPLETE)

1081 {

1082 pg_GSS_error(_("retrieving GSS user name failed"),

1083 maj_stat, min_stat);

1085 }

1086

1087

1088

1089

1090

1091 princ = palloc(gbuf.length + 1);

1092 memcpy(princ, gbuf.value, gbuf.length);

1093 princ[gbuf.length] = '\0';

1094 gss_release_buffer(&lmin_s, &gbuf);

1095

1096

1097

1098

1099

1100

1101

1102

1103

1106

1107

1108

1109

1110 if (strchr(princ, '@'))

1111 {

1112 char *cp = strchr(princ, '@');

1113

1114

1115

1116

1117

1118

1119 if (port->hba->include_realm)

1120 *cp = '\0';

1121 cp++;

1122

1123 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))

1124 {

1125

1126

1127

1130 else

1131 ret = strcmp(port->hba->krb_realm, cp);

1132

1133 if (ret)

1134 {

1135

1137 "GSSAPI realm (%s) and configured realm (%s) don't match",

1138 cp, port->hba->krb_realm);

1141 }

1142 }

1143 }

1144 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))

1145 {

1147 "GSSAPI did not return realm but realm matching was requested");

1150 }

1151

1154

1156

1157 return ret;

1158}

1159#endif

1160

1161

1162

1163

1164

1165

1166#ifdef ENABLE_SSPI

1167

1168

1169

1170

1171

1172static void

1173pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)

1174{

1175 char sysmsg[256];

1176

1177 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |

1178 FORMAT_MESSAGE_FROM_SYSTEM,

1179 NULL, r, 0,

1180 sysmsg, sizeof(sysmsg), NULL) == 0)

1184 else

1188}

1189

1190static int

1192{

1193 int mtype;

1195 SECURITY_STATUS r;

1196 CredHandle sspicred;

1197 CtxtHandle *sspictx = NULL,

1198 newctx;

1199 TimeStamp expiry;

1200 ULONG contextattr;

1201 SecBufferDesc inbuf;

1202 SecBufferDesc outbuf;

1203 SecBuffer OutBuffers[1];

1204 SecBuffer InBuffers[1];

1206 TOKEN_USER *tokenuser;

1207 DWORD retlen;

1210 DWORD accountnamesize = sizeof(accountname);

1211 DWORD domainnamesize = sizeof(domainname);

1212 SID_NAME_USE accountnameuse;

1214

1215

1216

1217

1218 r = AcquireCredentialsHandle(NULL,

1219 "negotiate",

1220 SECPKG_CRED_INBOUND,

1221 NULL,

1222 NULL,

1223 NULL,

1224 NULL,

1225 &sspicred,

1226 &expiry);

1227 if (r != SEC_E_OK)

1228 pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);

1229

1230

1231

1232

1233

1234

1235

1236 do

1237 {

1241 {

1242 if (sspictx != NULL)

1243 {

1244 DeleteSecurityContext(sspictx);

1245 free(sspictx);

1246 }

1247 FreeCredentialsHandle(&sspicred);

1248

1249

1250 if (mtype != EOF)

1252 (errcode(ERRCODE_PROTOCOL_VIOLATION),

1253 errmsg("expected SSPI response, got message type %d",

1254 mtype)));

1256 }

1257

1258

1261 {

1262

1264 if (sspictx != NULL)

1265 {

1266 DeleteSecurityContext(sspictx);

1267 free(sspictx);

1268 }

1269 FreeCredentialsHandle(&sspicred);

1271 }

1272

1273

1274 inbuf.ulVersion = SECBUFFER_VERSION;

1275 inbuf.cBuffers = 1;

1276 inbuf.pBuffers = InBuffers;

1277 InBuffers[0].pvBuffer = buf.data;

1278 InBuffers[0].cbBuffer = buf.len;

1279 InBuffers[0].BufferType = SECBUFFER_TOKEN;

1280

1281

1282 OutBuffers[0].pvBuffer = NULL;

1283 OutBuffers[0].BufferType = SECBUFFER_TOKEN;

1284 OutBuffers[0].cbBuffer = 0;

1285 outbuf.cBuffers = 1;

1286 outbuf.pBuffers = OutBuffers;

1287 outbuf.ulVersion = SECBUFFER_VERSION;

1288

1289 elog(DEBUG4, "processing received SSPI token of length %u",

1290 (unsigned int) buf.len);

1291

1292 r = AcceptSecurityContext(&sspicred,

1293 sspictx,

1294 &inbuf,

1295 ASC_REQ_ALLOCATE_MEMORY,

1296 SECURITY_NETWORK_DREP,

1297 &newctx,

1298 &outbuf,

1299 &contextattr,

1300 NULL);

1301

1302

1304

1305 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)

1306 {

1307

1308

1309

1310 elog(DEBUG4, "sending SSPI response token of length %u",

1311 (unsigned int) outbuf.pBuffers[0].cbBuffer);

1312

1313 port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;

1314 port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;

1315

1317 port->gss->outbuf.value, port->gss->outbuf.length);

1318

1319 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);

1320 }

1321

1322 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)

1323 {

1324 if (sspictx != NULL)

1325 {

1326 DeleteSecurityContext(sspictx);

1327 free(sspictx);

1328 }

1329 FreeCredentialsHandle(&sspicred);

1330 pg_SSPI_error(ERROR,

1331 _("could not accept SSPI security context"), r);

1332 }

1333

1334

1335

1336

1337

1338

1339

1340 if (sspictx == NULL)

1341 {

1342 sspictx = malloc(sizeof(CtxtHandle));

1343 if (sspictx == NULL)

1345 (errmsg("out of memory")));

1346 }

1347

1348 memcpy(sspictx, &newctx, sizeof(CtxtHandle));

1349

1350 if (r == SEC_I_CONTINUE_NEEDED)

1351 elog(DEBUG4, "SSPI continue needed");

1352

1353 } while (r == SEC_I_CONTINUE_NEEDED);

1354

1355

1356

1357

1358

1359 FreeCredentialsHandle(&sspicred);

1360

1361

1362

1363

1364

1365

1366

1367

1368

1369 r = QuerySecurityContextToken(sspictx, &token);

1370 if (r != SEC_E_OK)

1371 pg_SSPI_error(ERROR,

1372 _("could not get token from SSPI security context"), r);

1373

1374

1375

1376

1377

1378 DeleteSecurityContext(sspictx);

1379 free(sspictx);

1380

1381 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)

1383 (errmsg_internal("could not get token information buffer size: error code %lu",

1384 GetLastError())));

1385

1386 tokenuser = malloc(retlen);

1387 if (tokenuser == NULL)

1389 (errmsg("out of memory")));

1390

1391 if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))

1393 (errmsg_internal("could not get token information: error code %lu",

1394 GetLastError())));

1395

1396 CloseHandle(token);

1397

1398 if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,

1399 domainname, &domainnamesize, &accountnameuse))

1401 (errmsg_internal("could not look up account SID: error code %lu",

1402 GetLastError())));

1403

1404 free(tokenuser);

1405

1406 if (port->hba->compat_realm)

1407 {

1408 int status = pg_SSPI_make_upn(accountname, sizeof(accountname),

1409 domainname, sizeof(domainname),

1410 port->hba->upn_username);

1411

1413

1414 return status;

1415 }

1416

1417

1418

1419

1420

1421

1422

1423 if (port->hba->compat_realm)

1424 {

1425

1427 }

1428 else

1429 {

1430

1432 }

1433

1436

1437

1438

1439

1440

1441 if (port->hba->krb_realm && strlen(port->hba->krb_realm))

1442 {

1444 {

1446 "SSPI domain (%s) and configured domain (%s) don't match",

1447 domainname, port->hba->krb_realm);

1448

1450 }

1451 }

1452

1453

1454

1455

1456

1457

1458

1459 if (port->hba->include_realm)

1460 {

1461 char *namebuf;

1462 int retval;

1463

1464 namebuf = psprintf("%s@%s", accountname, domainname);

1467 return retval;

1468 }

1469 else

1471}

1472

1473

1474

1475

1476

1477static int

1478pg_SSPI_make_upn(char *accountname,

1479 size_t accountnamesize,

1480 char *domainname,

1481 size_t domainnamesize,

1482 bool update_accountname)

1483{

1484 char *samname;

1485 char *upname = NULL;

1486 char *p = NULL;

1487 ULONG upnamesize = 0;

1488 size_t upnamerealmsize;

1489 BOOLEAN res;

1490

1491

1492

1493

1494

1495

1496

1497

1498 samname = psprintf("%s\\%s", domainname, accountname);

1499 res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,

1500 NULL, &upnamesize);

1501

1502 if ((!res && GetLastError() != ERROR_INSUFFICIENT_BUFFER)

1503 || upnamesize == 0)

1504 {

1507 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),

1508 errmsg("could not translate name")));

1510 }

1511

1512

1513 upname = palloc(upnamesize);

1514

1515 res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,

1516 upname, &upnamesize);

1517

1519 if (res)

1520 p = strchr(upname, '@');

1521

1522 if (!res || p == NULL)

1523 {

1526 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),

1527 errmsg("could not translate name")));

1529 }

1530

1531

1532 upnamerealmsize = upnamesize - (p - upname + 1);

1533

1534

1535 if (upnamerealmsize > domainnamesize)

1536 {

1539 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),

1540 errmsg("realm name too long")));

1542 }

1543

1544

1545 strcpy(domainname, p + 1);

1546

1547

1548 if (update_accountname)

1549 {

1550 if ((p - upname + 1) > accountnamesize)

1551 {

1554 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),

1555 errmsg("translated account name too long")));

1557 }

1558

1559 *p = 0;

1560 strcpy(accountname, upname);

1561 }

1562

1565}

1566#endif

1567

1568

1569

1570

1571

1572

1573

1574

1575

1576

1577

1578

1579

1580

1581static bool

1583 char *ident_user)

1584{

1585 const char *cursor = ident_response;

1586

1587

1588

1589

1590 if (strlen(ident_response) < 2)

1591 return false;

1592 else if (ident_response[strlen(ident_response) - 2] != '\r')

1593 return false;

1594 else

1595 {

1597 cursor++;

1598

1600 return false;

1601 else

1602 {

1603

1604 char response_type[80];

1605 int i;

1606

1607 cursor++;

1609 cursor++;

1610 i = 0;

1612 i < (int) (sizeof(response_type) - 1))

1613 response_type[i++] = *cursor++;

1614 response_type[i] = '\0';

1616 cursor++;

1617 if (strcmp(response_type, "USERID") != 0)

1618 return false;

1619 else

1620 {

1621

1622

1623

1624

1626 return false;

1627 else

1628 {

1629 cursor++;

1630

1634 return false;

1635 else

1636 {

1637 cursor++;

1639 cursor++;

1640

1641 i = 0;

1643 ident_user[i++] = *cursor++;

1644 ident_user[i] = '\0';

1645 return true;

1646 }

1647 }

1648 }

1649 }

1650 }

1651}

1652

1653

1654

1655

1656

1657

1658

1659

1660

1661

1662static int

1664{

1669 int rc;

1670 bool ident_return;

1671 char remote_addr_s[NI_MAXHOST];

1672 char remote_port[NI_MAXSERV];

1673 char local_addr_s[NI_MAXHOST];

1674 char local_port[NI_MAXSERV];

1675 char ident_port[NI_MAXSERV];

1676 char ident_query[80];

1678 struct addrinfo *ident_serv = NULL,

1679 *la = NULL,

1680 hints;

1681

1682

1683

1684

1685

1687 remote_addr_s, sizeof(remote_addr_s),

1688 remote_port, sizeof(remote_port),

1689 NI_NUMERICHOST | NI_NUMERICSERV);

1691 local_addr_s, sizeof(local_addr_s),

1692 local_port, sizeof(local_port),

1693 NI_NUMERICHOST | NI_NUMERICSERV);

1694

1696 hints.ai_flags = AI_NUMERICHOST;

1697 hints.ai_family = remote_addr.addr.ss_family;

1698 hints.ai_socktype = SOCK_STREAM;

1699 hints.ai_protocol = 0;

1700 hints.ai_addrlen = 0;

1701 hints.ai_canonname = NULL;

1702 hints.ai_addr = NULL;

1703 hints.ai_next = NULL;

1704 rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);

1705 if (rc || !ident_serv)

1706 {

1707

1708 ident_return = false;

1709 goto ident_inet_done;

1710 }

1711

1712 hints.ai_flags = AI_NUMERICHOST;

1713 hints.ai_family = local_addr.addr.ss_family;

1714 hints.ai_socktype = SOCK_STREAM;

1715 hints.ai_protocol = 0;

1716 hints.ai_addrlen = 0;

1717 hints.ai_canonname = NULL;

1718 hints.ai_addr = NULL;

1719 hints.ai_next = NULL;

1721 if (rc || !la)

1722 {

1723

1724 ident_return = false;

1725 goto ident_inet_done;

1726 }

1727

1728 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,

1729 ident_serv->ai_protocol);

1731 {

1734 errmsg("could not create socket for Ident connection: %m")));

1735 ident_return = false;

1736 goto ident_inet_done;

1737 }

1738

1739

1740

1741

1742

1743

1744 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);

1745 if (rc != 0)

1746 {

1749 errmsg("could not bind to local address \"%s\": %m",

1750 local_addr_s)));

1751 ident_return = false;

1752 goto ident_inet_done;

1753 }

1754

1755 rc = connect(sock_fd, ident_serv->ai_addr,

1756 ident_serv->ai_addrlen);

1757 if (rc != 0)

1758 {

1761 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",

1762 remote_addr_s, ident_port)));

1763 ident_return = false;

1764 goto ident_inet_done;

1765 }

1766

1767

1768 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",

1769 remote_port, local_port);

1770

1771

1772 do

1773 {

1775

1776 rc = send(sock_fd, ident_query, strlen(ident_query), 0);

1777 } while (rc < 0 && errno == EINTR);

1778

1779 if (rc < 0)

1780 {

1783 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",

1784 remote_addr_s, ident_port)));

1785 ident_return = false;

1786 goto ident_inet_done;

1787 }

1788

1789 do

1790 {

1792

1793 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);

1794 } while (rc < 0 && errno == EINTR);

1795

1796 if (rc < 0)

1797 {

1800 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",

1801 remote_addr_s, ident_port)));

1802 ident_return = false;

1803 goto ident_inet_done;

1804 }

1805

1806 ident_response[rc] = '\0';

1808 if (!ident_return)

1810 (errmsg("invalidly formatted response from Ident server: \"%s\"",

1811 ident_response)));

1812

1813ident_inet_done:

1816 if (ident_serv)

1818 if (la)

1820

1821 if (ident_return)

1822 {

1823

1824

1825

1826

1827

1830 }

1832}

1833

1834

1835

1836

1837

1838

1839

1840

1841

1842

1843

1844

1845

1846

1847static int

1849{

1852#ifndef WIN32

1853 struct passwd pwbuf;

1854 struct passwd *pw;

1855 char buf[1024];

1856 int rc;

1857 int ret;

1858#endif

1859

1861 {

1862

1863 if (errno == ENOSYS)

1865 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

1866 errmsg("peer authentication is not supported on this platform")));

1867 else

1870 errmsg("could not get peer credentials: %m")));

1872 }

1873

1874#ifndef WIN32

1875 rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);

1876 if (rc != 0)

1877 {

1878 errno = rc;

1880 errmsg("could not look up local user ID %ld: %m", (long) uid));

1882 }

1883 else if (!pw)

1884 {

1886 errmsg("local user with ID %ld does not exist", (long) uid));

1888 }

1889

1890

1891

1892

1893

1894

1896

1899

1900 return ret;

1901#else

1902

1905#endif

1906}

1907

1908

1909

1910

1911

1912

1913#ifdef USE_PAM

1914

1915

1916

1917

1918

1919static int

1920pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,

1921 struct pam_response **resp, void *appdata_ptr)

1922{

1923 const char *passwd;

1924 struct pam_response *reply;

1925 int i;

1926

1927 if (appdata_ptr)

1928 passwd = (char *) appdata_ptr;

1929 else

1930 {

1931

1932

1933

1934

1935 passwd = pam_passwd;

1936 }

1937

1938 *resp = NULL;

1939

1940 if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)

1941 return PAM_CONV_ERR;

1942

1943

1944

1945

1946

1947 if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)

1948 {

1950 (errcode(ERRCODE_OUT_OF_MEMORY),

1951 errmsg("out of memory")));

1952 return PAM_CONV_ERR;

1953 }

1954

1955 for (i = 0; i < num_msg; i++)

1956 {

1957 switch (msg[i]->msg_style)

1958 {

1959 case PAM_PROMPT_ECHO_OFF:

1960 if (strlen(passwd) == 0)

1961 {

1962

1963

1964

1965

1966

1969 if (passwd == NULL)

1970 {

1971

1972

1973

1974

1975

1976 pam_no_password = true;

1977 goto fail;

1978 }

1979 }

1980 if ((reply[i].resp = strdup(passwd)) == NULL)

1981 goto fail;

1982 reply[i].resp_retcode = PAM_SUCCESS;

1983 break;

1984 case PAM_ERROR_MSG:

1986 (errmsg("error from underlying PAM layer: %s",

1987 msg[i]->msg)));

1988

1989 case PAM_TEXT_INFO:

1990

1991 if ((reply[i].resp = strdup("")) == NULL)

1992 goto fail;

1993 reply[i].resp_retcode = PAM_SUCCESS;

1994 break;

1995 default:

1997 (errmsg("unsupported PAM conversation %d/\"%s\"",

1998 msg[i]->msg_style,

1999 msg[i]->msg ? msg[i]->msg : "(none)")));

2000 goto fail;

2001 }

2002 }

2003

2004 *resp = reply;

2005 return PAM_SUCCESS;

2006

2007fail:

2008

2009 for (i = 0; i < num_msg; i++)

2010 free(reply[i].resp);

2011 free(reply);

2012

2013 return PAM_CONV_ERR;

2014}

2015

2016

2017

2018

2019

2020static int

2022{

2023 int retval;

2024 pam_handle_t *pamh = NULL;

2025

2026

2027

2028

2029

2030

2032 pam_port_cludge = port;

2033 pam_no_password = false;

2034

2035

2036

2037

2038

2039

2040 pam_passw_conv.appdata_ptr = unconstify(char *, password);

2041

2042

2043

2044 if (port->hba->pamservice && port->hba->pamservice[0] != '\0')

2045 retval = pam_start(port->hba->pamservice, "pgsql@",

2046 &pam_passw_conv, &pamh);

2047 else

2048 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",

2049 &pam_passw_conv, &pamh);

2050

2051 if (retval != PAM_SUCCESS)

2052 {

2054 (errmsg("could not create PAM authenticator: %s",

2055 pam_strerror(pamh, retval))));

2056 pam_passwd = NULL;

2058 }

2059

2060 retval = pam_set_item(pamh, PAM_USER, user);

2061

2062 if (retval != PAM_SUCCESS)

2063 {

2065 (errmsg("pam_set_item(PAM_USER) failed: %s",

2066 pam_strerror(pamh, retval))));

2067 pam_passwd = NULL;

2069 }

2070

2072 {

2073 char hostinfo[NI_MAXHOST];

2074 int flags;

2075

2076 if (port->hba->pam_use_hostname)

2077 flags = 0;

2078 else

2079 flags = NI_NUMERICHOST | NI_NUMERICSERV;

2080

2082 hostinfo, sizeof(hostinfo), NULL, 0,

2083 flags);

2084 if (retval != 0)

2085 {

2090 }

2091

2092 retval = pam_set_item(pamh, PAM_RHOST, hostinfo);

2093

2094 if (retval != PAM_SUCCESS)

2095 {

2097 (errmsg("pam_set_item(PAM_RHOST) failed: %s",

2098 pam_strerror(pamh, retval))));

2099 pam_passwd = NULL;

2101 }

2102 }

2103

2104 retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);

2105

2106 if (retval != PAM_SUCCESS)

2107 {

2109 (errmsg("pam_set_item(PAM_CONV) failed: %s",

2110 pam_strerror(pamh, retval))));

2111 pam_passwd = NULL;

2113 }

2114

2115 retval = pam_authenticate(pamh, 0);

2116

2117 if (retval != PAM_SUCCESS)

2118 {

2119

2120 if (!pam_no_password)

2122 (errmsg("pam_authenticate failed: %s",

2123 pam_strerror(pamh, retval))));

2124 pam_passwd = NULL;

2126 }

2127

2128 retval = pam_acct_mgmt(pamh, 0);

2129

2130 if (retval != PAM_SUCCESS)

2131 {

2132

2133 if (!pam_no_password)

2135 (errmsg("pam_acct_mgmt failed: %s",

2136 pam_strerror(pamh, retval))));

2137 pam_passwd = NULL;

2139 }

2140

2141 retval = pam_end(pamh, retval);

2142

2143 if (retval != PAM_SUCCESS)

2144 {

2146 (errmsg("could not release PAM authenticator: %s",

2147 pam_strerror(pamh, retval))));

2148 }

2149

2150 pam_passwd = NULL;

2151

2152 if (retval == PAM_SUCCESS)

2154

2156}

2157#endif

2158

2159

2160

2161

2162

2163

2164#ifdef USE_BSD_AUTH

2165static int

2167{

2168 char *passwd;

2169 int retval;

2170

2171

2173

2175 if (passwd == NULL)

2177

2178

2179

2180

2181

2182

2183 retval = auth_userokay(user, NULL, "auth-postgresql", passwd);

2184

2186

2187 if (!retval)

2189

2192}

2193#endif

2194

2195

2196

2197

2198

2199

2200#ifdef USE_LDAP

2201

2202static int errdetail_for_ldap(LDAP *ldap);

2203

2204

2205

2206

2207

2208static int

2209InitializeLDAPConnection(Port *port, LDAP **ldap)

2210{

2211 const char *scheme;

2212 int ldapversion = LDAP_VERSION3;

2213 int r;

2214

2215 scheme = port->hba->ldapscheme;

2216 if (scheme == NULL)

2217 scheme = "ldap";

2218#ifdef WIN32

2219 if (strcmp(scheme, "ldaps") == 0)

2220 *ldap = ldap_sslinit(port->hba->ldapserver, port->hba->ldapport, 1);

2221 else

2222 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);

2223 if (!*ldap)

2224 {

2226 (errmsg("could not initialize LDAP: error code %d",

2227 (int) LdapGetLastError())));

2228

2230 }

2231#else

2232#ifdef HAVE_LDAP_INITIALIZE

2233

2234

2235

2236

2237

2238

2239

2240

2241 {

2243 char *hostlist = NULL;

2244 char *p;

2245 bool append_port;

2246

2247

2249

2250

2251

2252

2253

2254

2255 if (port->hba->ldapserver || port->hba->ldapserver[0] == '\0')

2256 {

2257 char *domain;

2258

2259

2260 if (ldap_dn2domain(port->hba->ldapbasedn, &domain))

2261 {

2263 (errmsg("could not extract domain name from ldapbasedn")));

2265 }

2266

2267

2268 if (ldap_domain2hostlist(domain, &hostlist))

2269 {

2271 (errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",

2272 domain),

2273 (errhint("Set an LDAP server name explicitly."))));

2274 ldap_memfree(domain);

2276 }

2277 ldap_memfree(domain);

2278

2279

2280 p = hostlist;

2281 append_port = false;

2282 }

2283 else

2284 {

2285

2286 p = port->hba->ldapserver;

2287 append_port = true;

2288 }

2289

2290

2291 do

2292 {

2293 size_t size;

2294

2295

2296 size = strcspn(p, " ");

2297

2298

2299 if (uris.len > 0)

2301

2302

2306 if (append_port)

2308

2309

2310 p += size;

2311 while (*p == ' ')

2312 ++p;

2313 } while (*p);

2314

2315

2316 if (hostlist)

2317 ldap_memfree(hostlist);

2318

2319

2320 r = ldap_initialize(ldap, uris.data);

2322 if (r != LDAP_SUCCESS)

2323 {

2325 (errmsg("could not initialize LDAP: %s",

2326 ldap_err2string(r))));

2327

2329 }

2330 }

2331#else

2332 if (strcmp(scheme, "ldaps") == 0)

2333 {

2335 (errmsg("ldaps not supported with this LDAP library")));

2336

2338 }

2339 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);

2340 if (!*ldap)

2341 {

2343 (errmsg("could not initialize LDAP: %m")));

2344

2346 }

2347#endif

2348#endif

2349

2350 if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)

2351 {

2353 (errmsg("could not set LDAP protocol version: %s",

2354 ldap_err2string(r)),

2355 errdetail_for_ldap(*ldap)));

2356 ldap_unbind(*ldap);

2358 }

2359

2360 if (port->hba->ldaptls)

2361 {

2362#ifndef WIN32

2363 if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)

2364#else

2365 if ((r = ldap_start_tls_s(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)

2366#endif

2367 {

2369 (errmsg("could not start LDAP TLS session: %s",

2370 ldap_err2string(r)),

2371 errdetail_for_ldap(*ldap)));

2372 ldap_unbind(*ldap);

2374 }

2375 }

2376

2378}

2379

2380

2381#define LPH_USERNAME "$username"

2382#define LPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)

2383

2384

2385#ifndef LDAP_NO_ATTRS

2386#define LDAP_NO_ATTRS "1.1"

2387#endif

2388

2389

2390#ifndef LDAPS_PORT

2391#define LDAPS_PORT 636

2392#endif

2393

2394static char *

2395dummy_ldap_password_mutator(char *input)

2396{

2398}

2399

2400

2401

2402

2403

2404static char *

2405FormatSearchFilter(const char *pattern, const char *user_name)

2406{

2408

2410 while (*pattern != '\0')

2411 {

2412 if (strncmp(pattern, LPH_USERNAME, LPH_USERNAME_LEN) == 0)

2413 {

2415 pattern += LPH_USERNAME_LEN;

2416 }

2417 else

2419 }

2420

2422}

2423

2424

2425

2426

2427static int

2429{

2430 char *passwd;

2431 LDAP *ldap;

2432 int r;

2433 char *fulluser;

2434 const char *server_name;

2435

2436#ifdef HAVE_LDAP_INITIALIZE

2437

2438

2439

2440

2441

2442 if ((port->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&

2443 (port->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))

2444 {

2446 (errmsg("LDAP server not specified, and no ldapbasedn")));

2448 }

2449#else

2450 if (port->hba->ldapserver || port->hba->ldapserver[0] == '\0')

2451 {

2453 (errmsg("LDAP server not specified")));

2455 }

2456#endif

2457

2458

2459

2460

2461

2462 server_name = port->hba->ldapserver ? port->hba->ldapserver : "";

2463

2464 if (port->hba->ldapport == 0)

2465 {

2466 if (port->hba->ldapscheme != NULL &&

2467 strcmp(port->hba->ldapscheme, "ldaps") == 0)

2468 port->hba->ldapport = LDAPS_PORT;

2469 else

2470 port->hba->ldapport = LDAP_PORT;

2471 }

2472

2474

2476 if (passwd == NULL)

2477 return STATUS_EOF;

2478

2480 {

2481

2484 }

2485

2486 if (port->hba->ldapbasedn)

2487 {

2488

2489

2490

2491

2492 char *filter;

2493 LDAPMessage *search_message;

2494 LDAPMessage *entry;

2495 char *attributes[] = {LDAP_NO_ATTRS, NULL};

2496 char *dn;

2497 char *c;

2498 int count;

2499

2500

2501

2502

2503

2504

2505

2506 for (c = port->user_name; *c; c++)

2507 {

2508 if (*c == '*' ||

2509 *c == '(' ||

2510 *c == ')' ||

2511 *c == '\\' ||

2512 *c == '/')

2513 {

2515 (errmsg("invalid character in user name for LDAP authentication")));

2516 ldap_unbind(ldap);

2519 }

2520 }

2521

2522

2523

2524

2525

2526 r = ldap_simple_bind_s(ldap,

2527 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",

2529 if (r != LDAP_SUCCESS)

2530 {

2532 (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s",

2533 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",

2534 server_name,

2535 ldap_err2string(r)),

2536 errdetail_for_ldap(ldap)));

2537 ldap_unbind(ldap);

2540 }

2541

2542

2543 if (port->hba->ldapsearchfilter)

2544 filter = FormatSearchFilter(port->hba->ldapsearchfilter, port->user_name);

2545 else if (port->hba->ldapsearchattribute)

2546 filter = psprintf("(%s=%s)", port->hba->ldapsearchattribute, port->user_name);

2547 else

2548 filter = psprintf("(uid=%s)", port->user_name);

2549

2550 search_message = NULL;

2551 r = ldap_search_s(ldap,

2552 port->hba->ldapbasedn,

2553 port->hba->ldapscope,

2554 filter,

2555 attributes,

2556 0,

2557 &search_message);

2558

2559 if (r != LDAP_SUCCESS)

2560 {

2562 (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",

2563 filter, server_name, ldap_err2string(r)),

2564 errdetail_for_ldap(ldap)));

2565 if (search_message != NULL)

2566 ldap_msgfree(search_message);

2567 ldap_unbind(ldap);

2571 }

2572

2573 count = ldap_count_entries(ldap, search_message);

2574 if (count != 1)

2575 {

2576 if (count == 0)

2578 (errmsg("LDAP user \"%s\" does not exist", port->user_name),

2579 errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",

2580 filter, server_name)));

2581 else

2583 (errmsg("LDAP user \"%s\" is not unique", port->user_name),

2584 errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.",

2585 "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",

2586 count,

2587 filter, server_name, count)));

2588

2589 ldap_unbind(ldap);

2592 ldap_msgfree(search_message);

2594 }

2595

2596 entry = ldap_first_entry(ldap, search_message);

2597 dn = ldap_get_dn(ldap, entry);

2598 if (dn == NULL)

2599 {

2601

2602 (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);

2604 (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",

2605 filter, server_name,

2606 ldap_err2string(error)),

2607 errdetail_for_ldap(ldap)));

2608 ldap_unbind(ldap);

2611 ldap_msgfree(search_message);

2613 }

2615

2617 ldap_memfree(dn);

2618 ldap_msgfree(search_message);

2619 }

2620 else

2621 fulluser = psprintf("%s%s%s",

2622 port->hba->ldapprefix ? port->hba->ldapprefix : "",

2623 port->user_name,

2624 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");

2625

2626 r = ldap_simple_bind_s(ldap, fulluser, passwd);

2627

2628 if (r != LDAP_SUCCESS)

2629 {

2631 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",

2632 fulluser, server_name, ldap_err2string(r)),

2633 errdetail_for_ldap(ldap)));

2634 ldap_unbind(ldap);

2636 pfree(fulluser);

2638 }

2639

2640

2642

2643 ldap_unbind(ldap);

2645 pfree(fulluser);

2646

2648}

2649

2650

2651

2652

2653

2654static int

2655errdetail_for_ldap(LDAP *ldap)

2656{

2657 char *message;

2658 int rc;

2659

2660 rc = ldap_get_option(ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, &message);

2661 if (rc == LDAP_SUCCESS && message != NULL)

2662 {

2663 errdetail("LDAP diagnostics: %s", message);

2664 ldap_memfree(message);

2665 }

2666

2667 return 0;

2668}

2669

2670#endif

2671

2672

2673

2674

2675

2676

2677#ifdef USE_SSL

2678static int

2680{

2682 char *peer_username = NULL;

2683

2685

2686

2687 switch (port->hba->clientcertname)

2688 {

2690 peer_username = port->peer_dn;

2691 break;

2693 peer_username = port->peer_cn;

2694 }

2695

2696

2697 if (peer_username == NULL ||

2698 strlen(peer_username) <= 0)

2699 {

2701 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",

2702 port->user_name)));

2704 }

2705

2706 if (port->hba->auth_method == uaCert)

2707 {

2708

2709

2710

2711

2712

2713

2714

2715 if (port->peer_dn)

2716 {

2717

2718

2719

2720

2722 (errmsg("certificate authentication failed for user \"%s\": unable to retrieve subject DN",

2723 port->user_name)));

2725 }

2726

2728 }

2729

2730

2731 status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false);

2732 if (status_check_usermap != STATUS_OK)

2733 {

2734

2735

2736

2737

2738

2740 {

2741 switch (port->hba->clientcertname)

2742 {

2745 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",

2746 port->user_name)));

2747 break;

2750 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",

2751 port->user_name)));

2752 }

2753 }

2754 }

2755 return status_check_usermap;

2756}

2757#endif

2758

2759

2760

2761

2762

2763

2764

2765

2766

2767

2768

2769#define RADIUS_VECTOR_LENGTH 16

2770#define RADIUS_HEADER_LENGTH 20

2771#define RADIUS_MAX_PASSWORD_LENGTH 128

2772

2773

2774#define RADIUS_BUFFER_SIZE 1024

2775

2776typedef struct

2777{

2782

2783typedef struct

2784{

2789

2792

2793

2794#define RADIUS_ACCESS_REQUEST 1

2795#define RADIUS_ACCESS_ACCEPT 2

2796#define RADIUS_ACCESS_REJECT 3

2797

2798

2799#define RADIUS_USER_NAME 1

2800#define RADIUS_PASSWORD 2

2801#define RADIUS_SERVICE_TYPE 6

2802#define RADIUS_NAS_IDENTIFIER 32

2803

2804

2805#define RADIUS_AUTHENTICATE_ONLY 8

2806

2807

2808#define RADIUS_TIMEOUT 3

2809

2810static void

2812{

2814

2816 {

2817

2818

2819

2820

2821

2822

2824 "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",

2826 return;

2827 }

2828

2831 attr->length = len + 2;

2834}

2835

2836static int

2838{

2839 char *passwd;

2841 *secrets,

2842 *radiusports,

2843 *identifiers;

2844

2845

2847

2848

2849 if (port->hba->radiusservers == NIL)

2850 {

2852 (errmsg("RADIUS server not specified")));

2854 }

2855

2856 if (port->hba->radiussecrets == NIL)

2857 {

2859 (errmsg("RADIUS secret not specified")));

2861 }

2862

2863

2865

2867 if (passwd == NULL)

2868 return STATUS_EOF;

2869

2871 {

2876 }

2877

2878

2879

2880

2882 radiusports = list_head(port->hba->radiusports);

2883 identifiers = list_head(port->hba->radiusidentifiers);

2884 foreach(server, port->hba->radiusservers)

2885 {

2888 radiusports ? lfirst(radiusports) : NULL,

2889 identifiers ? lfirst(identifiers) : NULL,

2890 port->user_name,

2891 passwd);

2892

2893

2894

2895

2896

2897

2898

2900 {

2902

2905 }

2907 {

2910 }

2911

2912

2913

2914

2915

2916

2917

2919 secrets = lnext(port->hba->radiussecrets, secrets);

2921 radiusports = lnext(port->hba->radiusports, radiusports);

2923 identifiers = lnext(port->hba->radiusidentifiers, identifiers);

2924 }

2925

2926

2929}

2930

2931static int

2932PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)

2933{

2937 radius_packet *receivepacket = &radius_recv_pack;

2938 void *radius_buffer = &radius_send_pack;

2939 void *receive_buffer = &radius_recv_pack;

2941 uint8 *cryptvector;

2942 int encryptedpasswordlen;

2944 uint8 *md5trailer;

2945 int packetlength;

2947

2948 struct sockaddr_in6 localaddr;

2949 struct sockaddr_in6 remoteaddr;

2950 struct addrinfo hint;

2951 struct addrinfo *serveraddrs;

2954 fd_set fdset;

2955 struct timeval endtime;

2956 int i,

2957 j,

2958 r;

2959

2960

2963 if (identifier == NULL)

2964 identifier = "postgresql";

2965

2966 MemSet(&hint, 0, sizeof(hint));

2967 hint.ai_socktype = SOCK_DGRAM;

2968 hint.ai_family = AF_UNSPEC;

2970

2972 if (r || !serveraddrs)

2973 {

2975 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",

2977 if (serveraddrs)

2980 }

2981

2982

2983

2987 {

2989 (errmsg("could not generate random encryption vector")));

2992 }

2993 packet->id = packet->vector[0];

2997

2998

2999

3000

3001

3002

3003

3006 memcpy(cryptvector, secret, strlen(secret));

3007

3008

3009 md5trailer = packet->vector;

3011 {

3012 const char *errstr = NULL;

3013

3015

3016

3017

3018

3019

3020 md5trailer = encryptedpassword + i;

3021

3023 encryptedpassword + i, &errstr))

3024 {

3026 (errmsg("could not perform MD5 encryption of password: %s",

3027 errstr)));

3028 pfree(cryptvector);

3031 }

3032

3034 {

3035 if (j < strlen(passwd))

3036 encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];

3037 else

3038 encryptedpassword[j] = '\0' ^ encryptedpassword[j];

3039 }

3040 }

3041 pfree(cryptvector);

3042

3044

3045

3046 packetlength = packet->length;

3048

3049 sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);

3051 {

3053 (errmsg("could not create RADIUS socket: %m")));

3056 }

3057

3058 memset(&localaddr, 0, sizeof(localaddr));

3059 localaddr.sin6_family = serveraddrs[0].ai_family;

3060 localaddr.sin6_addr = in6addr_any;

3061 if (localaddr.sin6_family == AF_INET6)

3062 addrsize = sizeof(struct sockaddr_in6);

3063 else

3064 addrsize = sizeof(struct sockaddr_in);

3065

3066 if (bind(sock, (struct sockaddr *) &localaddr, addrsize))

3067 {

3069 (errmsg("could not bind local RADIUS socket: %m")));

3073 }

3074

3075 if (sendto(sock, radius_buffer, packetlength, 0,

3076 serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)

3077 {

3079 (errmsg("could not send RADIUS packet: %m")));

3083 }

3084

3085

3087

3088

3089

3090

3091

3092

3093

3094

3095

3096

3097

3100

3101 while (true)

3102 {

3103 struct timeval timeout;

3104 struct timeval now;

3105 int64 timeoutval;

3106 const char *errstr = NULL;

3107

3109 timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);

3110 if (timeoutval <= 0)

3111 {

3113 (errmsg("timeout waiting for RADIUS response from %s",

3114 server)));

3117 }

3118 timeout.tv_sec = timeoutval / 1000000;

3119 timeout.tv_usec = timeoutval % 1000000;

3120

3121 FD_ZERO(&fdset);

3122 FD_SET(sock, &fdset);

3123

3124 r = select(sock + 1, &fdset, NULL, NULL, &timeout);

3125 if (r < 0)

3126 {

3127 if (errno == EINTR)

3128 continue;

3129

3130

3132 (errmsg("could not check status on RADIUS socket: %m")));

3135 }

3136 if (r == 0)

3137 {

3139 (errmsg("timeout waiting for RADIUS response from %s",

3140 server)));

3143 }

3144

3145

3146

3147

3148

3149

3150

3151

3152

3153

3154

3155

3156 addrsize = sizeof(remoteaddr);

3157 packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,

3158 (struct sockaddr *) &remoteaddr, &addrsize);

3159 if (packetlength < 0)

3160 {

3162 (errmsg("could not read RADIUS response: %m")));

3165 }

3166

3168 {

3170 (errmsg("RADIUS response from %s was sent from incorrect port: %d",

3171 server, pg_ntoh16(remoteaddr.sin6_port))));

3172 continue;

3173 }

3174

3176 {

3178 (errmsg("RADIUS response from %s too short: %d", server, packetlength)));

3179 continue;

3180 }

3181

3183 {

3185 (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",

3186 server, pg_ntoh16(receivepacket->length), packetlength)));

3187 continue;

3188 }

3189

3190 if (packet->id != receivepacket->id)

3191 {

3193 (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",

3194 server, receivepacket->id, packet->id)));

3195 continue;

3196 }

3197

3198

3199

3200

3201

3202 cryptvector = palloc(packetlength + strlen(secret));

3203

3204 memcpy(cryptvector, receivepacket, 4);

3206

3207

3209

3213 memcpy(cryptvector + packetlength, secret, strlen(secret));

3214

3216 packetlength + strlen(secret),

3217 encryptedpassword, &errstr))

3218 {

3220 (errmsg("could not perform MD5 encryption of received packet: %s",

3221 errstr)));

3222 pfree(cryptvector);

3223 continue;

3224 }

3225 pfree(cryptvector);

3226

3228 {

3230 (errmsg("RADIUS response from %s has incorrect MD5 signature",

3231 server)));

3232 continue;

3233 }

3234

3236 {

3239 }

3241 {

3244 }

3245 else

3246 {

3248 (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",

3249 server, receivepacket->code, user_name)));

3250 continue;

3251 }

3252 }

3253}

const pg_be_sasl_mech pg_be_oauth_mech

int CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass, const char **logdetail)

const pg_be_sasl_mech pg_be_scram_mech

void sendAuthRequest(Port *port, AuthRequest areq, const void *extradata, int extralen)

static void radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)

#define RADIUS_HEADER_LENGTH

static int CheckPWChallengeAuth(Port *port, const char **logdetail)

#define RADIUS_AUTHENTICATE_ONLY

static int ident_inet(hbaPort *port)

char * pg_krb_server_keyfile

#define IDENT_USERNAME_MAX

#define RADIUS_ACCESS_REQUEST

bool pg_krb_caseins_users

static char * recv_password_packet(Port *port)

#define RADIUS_NAS_IDENTIFIER

#define RADIUS_SERVICE_TYPE

bool pg_gss_accept_delegation

static int CheckRADIUSAuth(Port *port)

static void auth_failed(Port *port, int status, const char *logdetail)

#define RADIUS_MAX_PASSWORD_LENGTH

ClientAuthentication_hook_type ClientAuthentication_hook

void ClientAuthentication(Port *port)

static int auth_peer(hbaPort *port)

#define RADIUS_ACCESS_REJECT

static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)

void set_authn_id(Port *port, const char *id)

#define RADIUS_ACCESS_ACCEPT

static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)

#define RADIUS_VECTOR_LENGTH

static bool interpret_ident_response(const char *ident_response, char *ident_user)

#define HOSTNAME_LOOKUP_DETAIL(port)

static int CheckPasswordAuth(Port *port, const char **logdetail)

#define RADIUS_BUFFER_SIZE

PGDLLIMPORT auth_password_hook_typ ldap_password_hook

void(* ClientAuthentication_hook_type)(Port *, int)

char *(* auth_password_hook_typ)(char *input)

#define PG_MAX_AUTH_TOKEN_LENGTH

Datum now(PG_FUNCTION_ARGS)

@ LOG_CONNECTION_AUTHENTICATION

void pg_store_delegated_credential(gss_cred_id_t cred)

void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)

bool secure_loaded_verify_locations(void)

#define unconstify(underlying_type, expr)

#define FLEXIBLE_ARRAY_MEMBER

#define MemSet(start, val, len)

int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const uint8 *md5_salt, int md5_salt_len, const char **logdetail)

int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)

char * get_role_password(const char *role, const char **logdetail)

PasswordType get_password_type(const char *shadow_pass)

int errcode_for_socket_access(void)

int errmsg_internal(const char *fmt,...)

int errdetail_internal(const char *fmt,...)

int errdetail(const char *fmt,...)

int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)

int errhint(const char *fmt,...)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

int errdetail_log(const char *fmt,...)

#define ereport(elevel,...)

#define ERRCODE_INVALID_PASSWORD

Assert(PointerIsAligned(start, uint64))

bool pg_isblank(const char c)

void hba_getauthmethod(hbaPort *port)

int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)

const char * hba_authname(UserAuth auth_method)

void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)

int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)

int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)

char * MemoryContextStrdup(MemoryContext context, const char *string)

void * MemoryContextAllocZero(MemoryContext context, Size size)

char * pstrdup(const char *in)

void pfree(void *pointer)

MemoryContext TopMemoryContext

bool pg_md5_binary(const void *buff, size_t len, uint8 *outbuf, const char **errstr)

#define CHECK_FOR_INTERRUPTS()

ClientConnectionInfo MyClientConnectionInfo

static int list_length(const List *l)

static ListCell * list_head(const List *l)

static ListCell * lnext(const List *l, const ListCell *c)

bool pg_strong_random(void *buf, size_t len)

int pg_strcasecmp(const char *s1, const char *s2)

int getpeereid(int sock, uid_t *uid, gid_t *gid)

int pq_getmessage(StringInfo s, int maxlen)

void pq_startmsgread(void)

void pq_sendbytes(StringInfo buf, const void *data, int datalen)

void pq_endmessage(StringInfo buf)

void pq_beginmessage(StringInfo buf, char msgtype)

static void pq_sendint32(StringInfo buf, uint32 i)

#define PqMsg_GSSResponse

#define PqMsg_AuthenticationRequest

#define AUTH_REQ_PASSWORD

#define AUTH_REQ_GSS_CONT

#define PqMsg_PasswordMessage

#define AUTH_REQ_SASL_FIN

char * psprintf(const char *fmt,...)

const char * gai_strerror(int ecode)

void appendStringInfo(StringInfo str, const char *fmt,...)

void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)

void appendStringInfoString(StringInfo str, const char *s)

void appendStringInfoChar(StringInfo str, char ch)

void initStringInfo(StringInfo str)

struct sockaddr_storage addr

uint8 data[FLEXIBLE_ARRAY_MEMBER]

uint8 vector[RADIUS_VECTOR_LENGTH]

#define bind(s, addr, addrlen)

#define recv(s, buf, len, flags)

#define send(s, buf, len, flags)

#define socket(af, type, protocol)

#define connect(s, name, namelen)

#define select(n, r, w, e, timeout)

int gettimeofday(struct timeval *tp, void *tzp)