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 (->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 (->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 (->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++)
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 (->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 ((->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&
2443 (->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))
2444 {
2446 (errmsg("LDAP server not specified, and no ldapbasedn")));
2448 }
2449#else
2450 if (->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 (->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
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)