1 /*-------------------------------------------------------------------------
2 *
3 * auth.c
4 * Routines to handle network authentication
5 *
6 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/libpq/auth.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16 #include "postgres.h"
17
18 #include <sys/param.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <unistd.h>
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25
26 #include "commands/user.h"
27 #include "common/ip.h"
28 #include "common/md5.h"
29 #include "common/scram-common.h"
30 #include "libpq/auth.h"
31 #include "libpq/crypt.h"
32 #include "libpq/libpq.h"
33 #include "libpq/pqformat.h"
34 #include "libpq/scram.h"
35 #include "miscadmin.h"
36 #include "port/pg_bswap.h"
37 #include "postmaster/postmaster.h"
38 #include "replication/walsender.h"
39 #include "storage/ipc.h"
40 #include "utils/guc.h"
41 #include "utils/memutils.h"
42 #include "utils/timestamp.h"
43
44 /*----------------------------------------------------------------
45 * Global authentication functions
46 *----------------------------------------------------------------
47 */
48 static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata,
49 int extralen);
50 static void auth_failed(Port *port, int status, char *logdetail);
51 static char *recv_password_packet(Port *port);
52 static void set_authn_id(Port *port, const char *id);
53
54
55 /*----------------------------------------------------------------
56 * Password-based authentication methods (password, md5, and scram-sha-256)
57 *----------------------------------------------------------------
58 */
59 static int CheckPasswordAuth(Port *port, char **logdetail);
60 static int CheckPWChallengeAuth(Port *port, char **logdetail);
61
62 static int CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail);
63 static int CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail);
64
65
66 /*----------------------------------------------------------------
67 * Ident authentication
68 *----------------------------------------------------------------
69 */
70 /* Max size of username ident server can return (per RFC 1413) */
71 #define IDENT_USERNAME_MAX 512
72
73 /* Standard TCP port number for Ident service. Assigned by IANA */
74 #define IDENT_PORT 113
75
76 static int ident_inet(hbaPort *port);
77
78
79 /*----------------------------------------------------------------
80 * Peer authentication
81 *----------------------------------------------------------------
82 */
83 static int auth_peer(hbaPort *port);
84
85
86 /*----------------------------------------------------------------
87 * PAM authentication
88 *----------------------------------------------------------------
89 */
90 #ifdef USE_PAM
91 #ifdef HAVE_PAM_PAM_APPL_H
92 #include <pam/pam_appl.h>
93 #endif
94 #ifdef HAVE_SECURITY_PAM_APPL_H
95 #include <security/pam_appl.h>
96 #endif
97
98 #define PGSQL_PAM_SERVICE "postgresql" /* Service name passed to PAM */
99
100 static int CheckPAMAuth(Port *port, const char *user, const char *password);
101 static int pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
102 struct pam_response **resp, void *appdata_ptr);
103
104 static struct pam_conv pam_passw_conv = {
105 &pam_passwd_conv_proc,
106 NULL
107 };
108
109 static const char *pam_passwd = NULL; /* Workaround for Solaris 2.6
110 * brokenness */
111 static Port *pam_port_cludge; /* Workaround for passing "Port *port" into
112 * pam_passwd_conv_proc */
113 static bool pam_no_password; /* For detecting no-password-given */
114 #endif /* USE_PAM */
115
116
117 /*----------------------------------------------------------------
118 * BSD authentication
119 *----------------------------------------------------------------
120 */
121 #ifdef USE_BSD_AUTH
122 #include <bsd_auth.h>
123
124 static int CheckBSDAuth(Port *port, char *user);
125 #endif /* USE_BSD_AUTH */
126
127
128 /*----------------------------------------------------------------
129 * LDAP authentication
130 *----------------------------------------------------------------
131 */
132 #ifdef USE_LDAP
133 #ifndef WIN32
134 /* We use a deprecated function to keep the codepath the same as win32. */
135 #define LDAP_DEPRECATED 1
136 #include <ldap.h>
137 #else
138 #include <winldap.h>
139
140 /* Correct header from the Platform SDK */
141 typedef
142 ULONG (*__ldap_start_tls_sA) (IN PLDAP ExternalHandle,
143 OUT PULONG ServerReturnValue,
144 OUT LDAPMessage **result,
145 IN PLDAPControlA * ServerControls,
146 IN PLDAPControlA * ClientControls
147 );
148 #endif
149
150 static int CheckLDAPAuth(Port *port);
151
152 /* LDAP_OPT_DIAGNOSTIC_MESSAGE is the newer spelling */
153 #ifndef LDAP_OPT_DIAGNOSTIC_MESSAGE
154 #define LDAP_OPT_DIAGNOSTIC_MESSAGE LDAP_OPT_ERROR_STRING
155 #endif
156
157 #endif /* USE_LDAP */
158
159 /*----------------------------------------------------------------
160 * Cert authentication
161 *----------------------------------------------------------------
162 */
163 #ifdef USE_SSL
164 static int CheckCertAuth(Port *port);
165 #endif
166
167
168 /*----------------------------------------------------------------
169 * Kerberos and GSSAPI GUCs
170 *----------------------------------------------------------------
171 */
172 char *pg_krb_server_keyfile;
173 bool pg_krb_caseins_users;
174
175
176 /*----------------------------------------------------------------
177 * GSSAPI Authentication
178 *----------------------------------------------------------------
179 */
180 #ifdef ENABLE_GSS
181 #include "libpq/be-gssapi-common.h"
182
183 static int pg_GSS_checkauth(Port *port);
184 static int pg_GSS_recvauth(Port *port);
185 #endif /* ENABLE_GSS */
186
187
188 /*----------------------------------------------------------------
189 * SSPI Authentication
190 *----------------------------------------------------------------
191 */
192 #ifdef ENABLE_SSPI
193 typedef SECURITY_STATUS
194 (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (PCtxtHandle, void **);
195 static int pg_SSPI_recvauth(Port *port);
196 static int pg_SSPI_make_upn(char *accountname,
197 size_t accountnamesize,
198 char *domainname,
199 size_t domainnamesize,
200 bool update_accountname);
201 #endif
202
203 /*----------------------------------------------------------------
204 * RADIUS Authentication
205 *----------------------------------------------------------------
206 */
207 static int CheckRADIUSAuth(Port *port);
208 static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd);
209
210
211 /*
212 * Maximum accepted size of GSS and SSPI authentication tokens.
213 * We also use this as a limit on ordinary password packet lengths.
214 *
215 * Kerberos tickets are usually quite small, but the TGTs issued by Windows
216 * domain controllers include an authorization field known as the Privilege
217 * Attribute Certificate (PAC), which contains the user's Windows permissions
218 * (group memberships etc.). The PAC is copied into all tickets obtained on
219 * the basis of this TGT (even those issued by Unix realms which the Windows
220 * realm trusts), and can be several kB in size. The maximum token size
221 * accepted by Windows systems is determined by the MaxAuthToken Windows
222 * registry setting. Microsoft recommends that it is not set higher than
223 * 65535 bytes, so that seems like a reasonable limit for us as well.
224 */
225 #define PG_MAX_AUTH_TOKEN_LENGTH 65535
226
227 /*
228 * Maximum accepted size of SASL messages.
229 *
230 * The messages that the server or libpq generate are much smaller than this,
231 * but have some headroom.
232 */
233 #define PG_MAX_SASL_MESSAGE_LENGTH 1024
234
235 /*----------------------------------------------------------------
236 * Global authentication functions
237 *----------------------------------------------------------------
238 */
239
240 /*
241 * This hook allows plugins to get control following client authentication,
242 * but before the user has been informed about the results. It could be used
243 * to record login events, insert a delay after failed authentication, etc.
244 */
245 ClientAuthentication_hook_type ClientAuthentication_hook = NULL;
246
247 /*
248 * Tell the user the authentication failed, but not (much about) why.
249 *
250 * There is a tradeoff here between security concerns and making life
251 * unnecessarily difficult for legitimate users. We would not, for example,
252 * want to report the password we were expecting to receive...
253 * But it seems useful to report the username and authorization method
254 * in use, and these are items that must be presumed known to an attacker
255 * anyway.
256 * Note that many sorts of failure report additional information in the
257 * postmaster log, which we hope is only readable by good guys. In
258 * particular, if logdetail isn't NULL, we send that string to the log.
259 */
260 static void
auth_failed(Port * port,int status,char * logdetail)261 auth_failed(Port *port, int status, char *logdetail)
262 {
263 const char *errstr;
264 char *cdetail;
265 int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
266
267 /*
268 * If we failed due to EOF from client, just quit; there's no point in
269 * trying to send a message to the client, and not much point in logging
270 * the failure in the postmaster log. (Logging the failure might be
271 * desirable, were it not for the fact that libpq closes the connection
272 * unceremoniously if challenged for a password when it hasn't got one to
273 * send. We'll get a useless log entry for every psql connection under
274 * password auth, even if it's perfectly successful, if we log STATUS_EOF
275 * events.)
276 */
277 if (status == STATUS_EOF)
278 proc_exit(0);
279
280 switch (port->hba->auth_method)
281 {
282 case uaReject:
283 case uaImplicitReject:
284 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
285 break;
286 case uaTrust:
287 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
288 break;
289 case uaIdent:
290 errstr = gettext_noop("Ident authentication failed for user \"%s\"");
291 break;
292 case uaPeer:
293 errstr = gettext_noop("Peer authentication failed for user \"%s\"");
294 break;
295 case uaPassword:
296 case uaMD5:
297 case uaSCRAM:
298 errstr = gettext_noop("password authentication failed for user \"%s\"");
299 /* We use it to indicate if a .pgpass password failed. */
300 errcode_return = ERRCODE_INVALID_PASSWORD;
301 break;
302 case uaGSS:
303 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
304 break;
305 case uaSSPI:
306 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
307 break;
308 case uaPAM:
309 errstr = gettext_noop("PAM authentication failed for user \"%s\"");
310 break;
311 case uaBSD:
312 errstr = gettext_noop("BSD authentication failed for user \"%s\"");
313 break;
314 case uaLDAP:
315 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
316 break;
317 case uaCert:
318 errstr = gettext_noop("certificate authentication failed for user \"%s\"");
319 break;
320 case uaRADIUS:
321 errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
322 break;
323 default:
324 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
325 break;
326 }
327
328 cdetail = psprintf(_("Connection matched pg_hba.conf line %d: \"%s\""),
329 port->hba->linenumber, port->hba->rawline);
330 if (logdetail)
331 logdetail = psprintf("%s\n%s", logdetail, cdetail);
332 else
333 logdetail = cdetail;
334
335 ereport(FATAL,
336 (errcode(errcode_return),
337 errmsg(errstr, port->user_name),
338 logdetail ? errdetail_log("%s", logdetail) : 0));
339
340 /* doesn't return */
341 }
342
343
344 /*
345 * Sets the authenticated identity for the current user. The provided string
346 * will be copied into the TopMemoryContext. The ID will be logged if
347 * log_connections is enabled.
348 *
349 * Auth methods should call this routine exactly once, as soon as the user is
350 * successfully authenticated, even if they have reasons to know that
351 * authorization will fail later.
352 *
353 * The provided string will be copied into TopMemoryContext, to match the
354 * lifetime of the Port, so it is safe to pass a string that is managed by an
355 * external library.
356 */
357 static void
set_authn_id(Port * port,const char * id)358 set_authn_id(Port *port, const char *id)
359 {
360 Assert(id);
361
362 if (port->authn_id)
363 {
364 /*
365 * An existing authn_id should never be overwritten; that means two
366 * authentication providers are fighting (or one is fighting itself).
367 * Don't leak any authn details to the client, but don't let the
368 * connection continue, either.
369 */
370 ereport(FATAL,
371 (errmsg("authentication identifier set more than once"),
372 errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
373 port->authn_id, id)));
374 }
375
376 port->authn_id = MemoryContextStrdup(TopMemoryContext, id);
377
378 if (Log_connections)
379 {
380 ereport(LOG,
381 errmsg("connection authenticated: identity=\"%s\" method=%s "
382 "(%s:%d)",
383 port->authn_id, hba_authname(port->hba->auth_method), HbaFileName,
384 port->hba->linenumber));
385 }
386 }
387
388
389 /*
390 * Client authentication starts here. If there is an error, this
391 * function does not return and the backend process is terminated.
392 */
393 void
ClientAuthentication(Port * port)394 ClientAuthentication(Port *port)
395 {
396 int status = STATUS_ERROR;
397 char *logdetail = NULL;
398
399 /*
400 * Get the authentication method to use for this frontend/database
401 * combination. Note: we do not parse the file at this point; this has
402 * already been done elsewhere. hba.c dropped an error message into the
403 * server logfile if parsing the hba config file failed.
404 */
405 hba_getauthmethod(port);
406
407 CHECK_FOR_INTERRUPTS();
408
409 /*
410 * This is the first point where we have access to the hba record for the
411 * current connection, so perform any verifications based on the hba
412 * options field that should be done *before* the authentication here.
413 */
414 if (port->hba->clientcert != clientCertOff)
415 {
416 /* If we haven't loaded a root certificate store, fail */
417 if (!secure_loaded_verify_locations())
418 ereport(FATAL,
419 (errcode(ERRCODE_CONFIG_FILE_ERROR),
420 errmsg("client certificates can only be checked if a root certificate store is available")));
421
422 /*
423 * If we loaded a root certificate store, and if a certificate is
424 * present on the client, then it has been verified against our root
425 * certificate store, and the connection would have been aborted
426 * already if it didn't verify ok.
427 */
428 if (!port->peer_cert_valid)
429 ereport(FATAL,
430 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
431 errmsg("connection requires a valid client certificate")));
432 }
433
434 /*
435 * Now proceed to do the actual authentication check
436 */
437 switch (port->hba->auth_method)
438 {
439 case uaReject:
440
441 /*
442 * An explicit "reject" entry in pg_hba.conf. This report exposes
443 * the fact that there's an explicit reject entry, which is
444 * perhaps not so desirable from a security standpoint; but the
445 * message for an implicit reject could confuse the DBA a lot when
446 * the true situation is a match to an explicit reject. And we
447 * don't want to change the message for an implicit reject. As
448 * noted below, the additional information shown here doesn't
449 * expose anything not known to an attacker.
450 */
451 {
452 char hostinfo[NI_MAXHOST];
453 const char *encryption_state;
454
455 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
456 hostinfo, sizeof(hostinfo),
457 NULL, 0,
458 NI_NUMERICHOST);
459
460 encryption_state =
461 #ifdef ENABLE_GSS
462 (port->gss && port->gss->enc) ? _("GSS encryption") :
463 #endif
464 #ifdef USE_SSL
465 port->ssl_in_use ? _("SSL encryption") :
466 #endif
467 _("no encryption");
468
469 if (am_walsender && !am_db_walsender)
470 ereport(FATAL,
471 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
472 /* translator: last %s describes encryption state */
473 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
474 hostinfo, port->user_name,
475 encryption_state)));
476 else
477 ereport(FATAL,
478 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
479 /* translator: last %s describes encryption state */
480 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
481 hostinfo, port->user_name,
482 port->database_name,
483 encryption_state)));
484 break;
485 }
486
487 case uaImplicitReject:
488
489 /*
490 * No matching entry, so tell the user we fell through.
491 *
492 * NOTE: the extra info reported here is not a security breach,
493 * because all that info is known at the frontend and must be
494 * assumed known to bad guys. We're merely helping out the less
495 * clueful good guys.
496 */
497 {
498 char hostinfo[NI_MAXHOST];
499 const char *encryption_state;
500
501 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
502 hostinfo, sizeof(hostinfo),
503 NULL, 0,
504 NI_NUMERICHOST);
505
506 encryption_state =
507 #ifdef ENABLE_GSS
508 (port->gss && port->gss->enc) ? _("GSS encryption") :
509 #endif
510 #ifdef USE_SSL
511 port->ssl_in_use ? _("SSL encryption") :
512 #endif
513 _("no encryption");
514
515 #define HOSTNAME_LOOKUP_DETAIL(port) \
516 (port->remote_hostname ? \
517 (port->remote_hostname_resolv == +1 ? \
518 errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
519 port->remote_hostname) : \
520 port->remote_hostname_resolv == 0 ? \
521 errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
522 port->remote_hostname) : \
523 port->remote_hostname_resolv == -1 ? \
524 errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
525 port->remote_hostname) : \
526 port->remote_hostname_resolv == -2 ? \
527 errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
528 port->remote_hostname, \
529 gai_strerror(port->remote_hostname_errcode)) : \
530 0) \
531 : (port->remote_hostname_resolv == -2 ? \
532 errdetail_log("Could not resolve client IP address to a host name: %s.", \
533 gai_strerror(port->remote_hostname_errcode)) : \
534 0))
535
536 if (am_walsender && !am_db_walsender)
537 ereport(FATAL,
538 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
539 /* translator: last %s describes encryption state */
540 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
541 hostinfo, port->user_name,
542 encryption_state),
543 HOSTNAME_LOOKUP_DETAIL(port)));
544 else
545 ereport(FATAL,
546 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
547 /* translator: last %s describes encryption state */
548 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
549 hostinfo, port->user_name,
550 port->database_name,
551 encryption_state),
552 HOSTNAME_LOOKUP_DETAIL(port)));
553 break;
554 }
555
556 case uaGSS:
557 #ifdef ENABLE_GSS
558 /* We might or might not have the gss workspace already */
559 if (port->gss == NULL)
560 port->gss = (pg_gssinfo *)
561 MemoryContextAllocZero(TopMemoryContext,
562 sizeof(pg_gssinfo));
563 port->gss->auth = true;
564
565 /*
566 * If GSS state was set up while enabling encryption, we can just
567 * check the client's principal. Otherwise, ask for it.
568 */
569 if (port->gss->enc)
570 status = pg_GSS_checkauth(port);
571 else
572 {
573 sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
574 status = pg_GSS_recvauth(port);
575 }
576 #else
577 Assert(false);
578 #endif
579 break;
580
581 case uaSSPI:
582 #ifdef ENABLE_SSPI
583 if (port->gss == NULL)
584 port->gss = (pg_gssinfo *)
585 MemoryContextAllocZero(TopMemoryContext,
586 sizeof(pg_gssinfo));
587 sendAuthRequest(port, AUTH_REQ_SSPI, NULL, 0);
588 status = pg_SSPI_recvauth(port);
589 #else
590 Assert(false);
591 #endif
592 break;
593
594 case uaPeer:
595 status = auth_peer(port);
596 break;
597
598 case uaIdent:
599 status = ident_inet(port);
600 break;
601
602 case uaMD5:
603 case uaSCRAM:
604 status = CheckPWChallengeAuth(port, &logdetail);
605 break;
606
607 case uaPassword:
608 status = CheckPasswordAuth(port, &logdetail);
609 break;
610
611 case uaPAM:
612 #ifdef USE_PAM
613 status = CheckPAMAuth(port, port->user_name, "");
614 #else
615 Assert(false);
616 #endif /* USE_PAM */
617 break;
618
619 case uaBSD:
620 #ifdef USE_BSD_AUTH
621 status = CheckBSDAuth(port, port->user_name);
622 #else
623 Assert(false);
624 #endif /* USE_BSD_AUTH */
625 break;
626
627 case uaLDAP:
628 #ifdef USE_LDAP
629 status = CheckLDAPAuth(port);
630 #else
631 Assert(false);
632 #endif
633 break;
634 case uaRADIUS:
635 status = CheckRADIUSAuth(port);
636 break;
637 case uaCert:
638 /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
639 case uaTrust:
640 status = STATUS_OK;
641 break;
642 }
643
644 if ((status == STATUS_OK && port->hba->clientcert == clientCertFull)
645 || port->hba->auth_method == uaCert)
646 {
647 /*
648 * Make sure we only check the certificate if we use the cert method
649 * or verify-full option.
650 */
651 #ifdef USE_SSL
652 status = CheckCertAuth(port);
653 #else
654 Assert(false);
655 #endif
656 }
657
658 if (ClientAuthentication_hook)
659 (*ClientAuthentication_hook) (port, status);
660
661 if (status == STATUS_OK)
662 sendAuthRequest(port, AUTH_REQ_OK, NULL, 0);
663 else
664 auth_failed(port, status, logdetail);
665 }
666
667
668 /*
669 * Send an authentication request packet to the frontend.
670 */
671 static void
sendAuthRequest(Port * port,AuthRequest areq,const char * extradata,int extralen)672 sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
673 {
674 StringInfoData buf;
675
676 CHECK_FOR_INTERRUPTS();
677
678 pq_beginmessage(&buf, 'R');
679 pq_sendint32(&buf, (int32) areq);
680 if (extralen > 0)
681 pq_sendbytes(&buf, extradata, extralen);
682
683 pq_endmessage(&buf);
684
685 /*
686 * Flush message so client will see it, except for AUTH_REQ_OK and
687 * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
688 * queries.
689 */
690 if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
691 pq_flush();
692
693 CHECK_FOR_INTERRUPTS();
694 }
695
696 /*
697 * Collect password response packet from frontend.
698 *
699 * Returns NULL if couldn't get password, else palloc'd string.
700 */
701 static char *
recv_password_packet(Port * port)702 recv_password_packet(Port *port)
703 {
704 StringInfoData buf;
705 int mtype;
706
707 pq_startmsgread();
708
709 /* Expect 'p' message type */
710 mtype = pq_getbyte();
711 if (mtype != 'p')
712 {
713 /*
714 * If the client just disconnects without offering a password, don't
715 * make a log entry. This is legal per protocol spec and in fact
716 * commonly done by psql, so complaining just clutters the log.
717 */
718 if (mtype != EOF)
719 ereport(ERROR,
720 (errcode(ERRCODE_PROTOCOL_VIOLATION),
721 errmsg("expected password response, got message type %d",
722 mtype)));
723 return NULL; /* EOF or bad message type */
724 }
725
726 initStringInfo(&buf);
727 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH)) /* receive password */
728 {
729 /* EOF - pq_getmessage already logged a suitable message */
730 pfree(buf.data);
731 return NULL;
732 }
733
734 /*
735 * Apply sanity check: password packet length should agree with length of
736 * contained string. Note it is safe to use strlen here because
737 * StringInfo is guaranteed to have an appended '\0'.
738 */
739 if (strlen(buf.data) + 1 != buf.len)
740 ereport(ERROR,
741 (errcode(ERRCODE_PROTOCOL_VIOLATION),
742 errmsg("invalid password packet size")));
743
744 /*
745 * Don't allow an empty password. Libpq treats an empty password the same
746 * as no password at all, and won't even try to authenticate. But other
747 * clients might, so allowing it would be confusing.
748 *
749 * Note that this only catches an empty password sent by the client in
750 * plaintext. There's also a check in CREATE/ALTER USER that prevents an
751 * empty string from being stored as a user's password in the first place.
752 * We rely on that for MD5 and SCRAM authentication, but we still need
753 * this check here, to prevent an empty password from being used with
754 * authentication methods that check the password against an external
755 * system, like PAM, LDAP and RADIUS.
756 */
757 if (buf.len == 1)
758 ereport(ERROR,
759 (errcode(ERRCODE_INVALID_PASSWORD),
760 errmsg("empty password returned by client")));
761
762 /* Do not echo password to logs, for security. */
763 elog(DEBUG5, "received password packet");
764
765 /*
766 * Return the received string. Note we do not attempt to do any
767 * character-set conversion on it; since we don't yet know the client's
768 * encoding, there wouldn't be much point.
769 */
770 return buf.data;
771 }
772
773
774 /*----------------------------------------------------------------
775 * Password-based authentication mechanisms
776 *----------------------------------------------------------------
777 */
778
779 /*
780 * Plaintext password authentication.
781 */
782 static int
CheckPasswordAuth(Port * port,char ** logdetail)783 CheckPasswordAuth(Port *port, char **logdetail)
784 {
785 char *passwd;
786 int result;
787 char *shadow_pass;
788
789 sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
790
791 passwd = recv_password_packet(port);
792 if (passwd == NULL)
793 return STATUS_EOF; /* client wouldn't send password */
794
795 shadow_pass = get_role_password(port->user_name, logdetail);
796 if (shadow_pass)
797 {
798 result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
799 logdetail);
800 }
801 else
802 result = STATUS_ERROR;
803
804 if (shadow_pass)
805 pfree(shadow_pass);
806 pfree(passwd);
807
808 if (result == STATUS_OK)
809 set_authn_id(port, port->user_name);
810
811 return result;
812 }
813
814 /*
815 * MD5 and SCRAM authentication.
816 */
817 static int
CheckPWChallengeAuth(Port * port,char ** logdetail)818 CheckPWChallengeAuth(Port *port, char **logdetail)
819 {
820 int auth_result;
821 char *shadow_pass;
822 PasswordType pwtype;
823
824 Assert(port->hba->auth_method == uaSCRAM ||
825 port->hba->auth_method == uaMD5);
826
827 /* First look up the user's password. */
828 shadow_pass = get_role_password(port->user_name, logdetail);
829
830 /*
831 * If the user does not exist, or has no password or it's expired, we
832 * still go through the motions of authentication, to avoid revealing to
833 * the client that the user didn't exist. If 'md5' is allowed, we choose
834 * whether to use 'md5' or 'scram-sha-256' authentication based on current
835 * password_encryption setting. The idea is that most genuine users
836 * probably have a password of that type, and if we pretend that this user
837 * had a password of that type, too, it "blends in" best.
838 */
839 if (!shadow_pass)
840 pwtype = Password_encryption;
841 else
842 pwtype = get_password_type(shadow_pass);
843
844 /*
845 * If 'md5' authentication is allowed, decide whether to perform 'md5' or
846 * 'scram-sha-256' authentication based on the type of password the user
847 * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
848 * SCRAM secret, we must do SCRAM authentication.
849 *
850 * If MD5 authentication is not allowed, always use SCRAM. If the user
851 * had an MD5 password, CheckSCRAMAuth() will fail.
852 */
853 if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
854 auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
855 else
856 auth_result = CheckSCRAMAuth(port, shadow_pass, logdetail);
857
858 if (shadow_pass)
859 pfree(shadow_pass);
860
861 /*
862 * If get_role_password() returned error, return error, even if the
863 * authentication succeeded.
864 */
865 if (!shadow_pass)
866 {
867 Assert(auth_result != STATUS_OK);
868 return STATUS_ERROR;
869 }
870
871 if (auth_result == STATUS_OK)
872 set_authn_id(port, port->user_name);
873
874 return auth_result;
875 }
876
877 static int
CheckMD5Auth(Port * port,char * shadow_pass,char ** logdetail)878 CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail)
879 {
880 char md5Salt[4]; /* Password salt */
881 char *passwd;
882 int result;
883
884 if (Db_user_namespace)
885 ereport(FATAL,
886 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
887 errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
888
889 /* include the salt to use for computing the response */
890 if (!pg_strong_random(md5Salt, 4))
891 {
892 ereport(LOG,
893 (errmsg("could not generate random MD5 salt")));
894 return STATUS_ERROR;
895 }
896
897 sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
898
899 passwd = recv_password_packet(port);
900 if (passwd == NULL)
901 return STATUS_EOF; /* client wouldn't send password */
902
903 if (shadow_pass)
904 result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
905 md5Salt, 4, logdetail);
906 else
907 result = STATUS_ERROR;
908
909 pfree(passwd);
910
911 return result;
912 }
913
914 static int
CheckSCRAMAuth(Port * port,char * shadow_pass,char ** logdetail)915 CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail)
916 {
917 StringInfoData sasl_mechs;
918 int mtype;
919 StringInfoData buf;
920 void *scram_opaq = NULL;
921 char *output = NULL;
922 int outputlen = 0;
923 const char *input;
924 int inputlen;
925 int result;
926 bool initial;
927
928 /*
929 * Send the SASL authentication request to user. It includes the list of
930 * authentication mechanisms that are supported.
931 */
932 initStringInfo(&sasl_mechs);
933
934 pg_be_scram_get_mechanisms(port, &sasl_mechs);
935 /* Put another '\0' to mark that list is finished. */
936 appendStringInfoChar(&sasl_mechs, '\0');
937
938 sendAuthRequest(port, AUTH_REQ_SASL, sasl_mechs.data, sasl_mechs.len);
939 pfree(sasl_mechs.data);
940
941 /*
942 * Loop through SASL message exchange. This exchange can consist of
943 * multiple messages sent in both directions. First message is always
944 * from the client. All messages from client to server are password
945 * packets (type 'p').
946 */
947 initial = true;
948 do
949 {
950 pq_startmsgread();
951 mtype = pq_getbyte();
952 if (mtype != 'p')
953 {
954 /* Only log error if client didn't disconnect. */
955 if (mtype != EOF)
956 {
957 ereport(ERROR,
958 (errcode(ERRCODE_PROTOCOL_VIOLATION),
959 errmsg("expected SASL response, got message type %d",
960 mtype)));
961 }
962 else
963 return STATUS_EOF;
964 }
965
966 /* Get the actual SASL message */
967 initStringInfo(&buf);
968 if (pq_getmessage(&buf, PG_MAX_SASL_MESSAGE_LENGTH))
969 {
970 /* EOF - pq_getmessage already logged error */
971 pfree(buf.data);
972 return STATUS_ERROR;
973 }
974
975 elog(DEBUG4, "processing received SASL response of length %d", buf.len);
976
977 /*
978 * The first SASLInitialResponse message is different from the others.
979 * It indicates which SASL mechanism the client selected, and contains
980 * an optional Initial Client Response payload. The subsequent
981 * SASLResponse messages contain just the SASL payload.
982 */
983 if (initial)
984 {
985 const char *selected_mech;
986
987 selected_mech = pq_getmsgrawstring(&buf);
988
989 /*
990 * Initialize the status tracker for message exchanges.
991 *
992 * If the user doesn't exist, or doesn't have a valid password, or
993 * it's expired, we still go through the motions of SASL
994 * authentication, but tell the authentication method that the
995 * authentication is "doomed". That is, it's going to fail, no
996 * matter what.
997 *
998 * This is because we don't want to reveal to an attacker what
999 * usernames are valid, nor which users have a valid password.
1000 */
1001 scram_opaq = pg_be_scram_init(port, selected_mech, shadow_pass);
1002
1003 inputlen = pq_getmsgint(&buf, 4);
1004 if (inputlen == -1)
1005 input = NULL;
1006 else
1007 input = pq_getmsgbytes(&buf, inputlen);
1008
1009 initial = false;
1010 }
1011 else
1012 {
1013 inputlen = buf.len;
1014 input = pq_getmsgbytes(&buf, buf.len);
1015 }
1016 pq_getmsgend(&buf);
1017
1018 /*
1019 * The StringInfo guarantees that there's a \0 byte after the
1020 * response.
1021 */
1022 Assert(input == NULL || input[inputlen] == '\0');
1023
1024 /*
1025 * we pass 'logdetail' as NULL when doing a mock authentication,
1026 * because we should already have a better error message in that case
1027 */
1028 result = pg_be_scram_exchange(scram_opaq, input, inputlen,
1029 &output, &outputlen,
1030 logdetail);
1031
1032 /* input buffer no longer used */
1033 pfree(buf.data);
1034
1035 if (output)
1036 {
1037 /*
1038 * Negotiation generated data to be sent to the client.
1039 */
1040 elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
1041
1042 if (result == SASL_EXCHANGE_SUCCESS)
1043 sendAuthRequest(port, AUTH_REQ_SASL_FIN, output, outputlen);
1044 else
1045 sendAuthRequest(port, AUTH_REQ_SASL_CONT, output, outputlen);
1046
1047 pfree(output);
1048 }
1049 } while (result == SASL_EXCHANGE_CONTINUE);
1050
1051 /* Oops, Something bad happened */
1052 if (result != SASL_EXCHANGE_SUCCESS)
1053 {
1054 return STATUS_ERROR;
1055 }
1056
1057 return STATUS_OK;
1058 }
1059
1060
1061 /*----------------------------------------------------------------
1062 * GSSAPI authentication system
1063 *----------------------------------------------------------------
1064 */
1065 #ifdef ENABLE_GSS
1066 static int
pg_GSS_recvauth(Port * port)1067 pg_GSS_recvauth(Port *port)
1068 {
1069 OM_uint32 maj_stat,
1070 min_stat,
1071 lmin_s,
1072 gflags;
1073 int mtype;
1074 StringInfoData buf;
1075 gss_buffer_desc gbuf;
1076
1077 /*
1078 * Use the configured keytab, if there is one. Unfortunately, Heimdal
1079 * doesn't support the cred store extensions, so use the env var.
1080 */
1081 if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
1082 {
1083 if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
1084 {
1085 /* The only likely failure cause is OOM, so use that errcode */
1086 ereport(FATAL,
1087 (errcode(ERRCODE_OUT_OF_MEMORY),
1088 errmsg("could not set environment: %m")));
1089 }
1090 }
1091
1092 /*
1093 * We accept any service principal that's present in our keytab. This
1094 * increases interoperability between kerberos implementations that see
1095 * for example case sensitivity differently, while not really opening up
1096 * any vector of attack.
1097 */
1098 port->gss->cred = GSS_C_NO_CREDENTIAL;
1099
1100 /*
1101 * Initialize sequence with an empty context
1102 */
1103 port->gss->ctx = GSS_C_NO_CONTEXT;
1104
1105 /*
1106 * Loop through GSSAPI message exchange. This exchange can consist of
1107 * multiple messages sent in both directions. First message is always from
1108 * the client. All messages from client to server are password packets
1109 * (type 'p').
1110 */
1111 do
1112 {
1113 pq_startmsgread();
1114
1115 CHECK_FOR_INTERRUPTS();
1116
1117 mtype = pq_getbyte();
1118 if (mtype != 'p')
1119 {
1120 /* Only log error if client didn't disconnect. */
1121 if (mtype != EOF)
1122 ereport(ERROR,
1123 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1124 errmsg("expected GSS response, got message type %d",
1125 mtype)));
1126 return STATUS_ERROR;
1127 }
1128
1129 /* Get the actual GSS token */
1130 initStringInfo(&buf);
1131 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
1132 {
1133 /* EOF - pq_getmessage already logged error */
1134 pfree(buf.data);
1135 return STATUS_ERROR;
1136 }
1137
1138 /* Map to GSSAPI style buffer */
1139 gbuf.length = buf.len;
1140 gbuf.value = buf.data;
1141
1142 elog(DEBUG4, "processing received GSS token of length %u",
1143 (unsigned int) gbuf.length);
1144
1145 maj_stat = gss_accept_sec_context(&min_stat,
1146 &port->gss->ctx,
1147 port->gss->cred,
1148 &gbuf,
1149 GSS_C_NO_CHANNEL_BINDINGS,
1150 &port->gss->name,
1151 NULL,
1152 &port->gss->outbuf,
1153 &gflags,
1154 NULL,
1155 NULL);
1156
1157 /* gbuf no longer used */
1158 pfree(buf.data);
1159
1160 elog(DEBUG5, "gss_accept_sec_context major: %d, "
1161 "minor: %d, outlen: %u, outflags: %x",
1162 maj_stat, min_stat,
1163 (unsigned int) port->gss->outbuf.length, gflags);
1164
1165 CHECK_FOR_INTERRUPTS();
1166
1167 if (port->gss->outbuf.length != 0)
1168 {
1169 /*
1170 * Negotiation generated data to be sent to the client.
1171 */
1172 elog(DEBUG4, "sending GSS response token of length %u",
1173 (unsigned int) port->gss->outbuf.length);
1174
1175 sendAuthRequest(port, AUTH_REQ_GSS_CONT,
1176 port->gss->outbuf.value, port->gss->outbuf.length);
1177
1178 gss_release_buffer(&lmin_s, &port->gss->outbuf);
1179 }
1180
1181 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
1182 {
1183 gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
1184 pg_GSS_error(_("accepting GSS security context failed"),
1185 maj_stat, min_stat);
1186 return STATUS_ERROR;
1187 }
1188
1189 if (maj_stat == GSS_S_CONTINUE_NEEDED)
1190 elog(DEBUG4, "GSS continue needed");
1191
1192 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
1193
1194 if (port->gss->cred != GSS_C_NO_CREDENTIAL)
1195 {
1196 /*
1197 * Release service principal credentials
1198 */
1199 gss_release_cred(&min_stat, &port->gss->cred);
1200 }
1201 return pg_GSS_checkauth(port);
1202 }
1203
1204 /*
1205 * Check whether the GSSAPI-authenticated user is allowed to connect as the
1206 * claimed username.
1207 */
1208 static int
pg_GSS_checkauth(Port * port)1209 pg_GSS_checkauth(Port *port)
1210 {
1211 int ret;
1212 OM_uint32 maj_stat,
1213 min_stat,
1214 lmin_s;
1215 gss_buffer_desc gbuf;
1216 char *princ;
1217
1218 /*
1219 * Get the name of the user that authenticated, and compare it to the pg
1220 * username that was specified for the connection.
1221 */
1222 maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
1223 if (maj_stat != GSS_S_COMPLETE)
1224 {
1225 pg_GSS_error(_("retrieving GSS user name failed"),
1226 maj_stat, min_stat);
1227 return STATUS_ERROR;
1228 }
1229
1230 /*
1231 * gbuf.value might not be null-terminated, so turn it into a regular
1232 * null-terminated string.
1233 */
1234 princ = palloc(gbuf.length + 1);
1235 memcpy(princ, gbuf.value, gbuf.length);
1236 princ[gbuf.length] = '\0';
1237 gss_release_buffer(&lmin_s, &gbuf);
1238
1239 /*
1240 * Copy the original name of the authenticated principal into our backend
1241 * memory for display later.
1242 *
1243 * This is also our authenticated identity. Set it now, rather than
1244 * waiting for the usermap check below, because authentication has already
1245 * succeeded and we want the log file to reflect that.
1246 */
1247 port->gss->princ = MemoryContextStrdup(TopMemoryContext, princ);
1248 set_authn_id(port, princ);
1249
1250 /*
1251 * Split the username at the realm separator
1252 */
1253 if (strchr(princ, '@'))
1254 {
1255 char *cp = strchr(princ, '@');
1256
1257 /*
1258 * If we are not going to include the realm in the username that is
1259 * passed to the ident map, destructively modify it here to remove the
1260 * realm. Then advance past the separator to check the realm.
1261 */
1262 if (!port->hba->include_realm)
1263 *cp = '\0';
1264 cp++;
1265
1266 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
1267 {
1268 /*
1269 * Match the realm part of the name first
1270 */
1271 if (pg_krb_caseins_users)
1272 ret = pg_strcasecmp(port->hba->krb_realm, cp);
1273 else
1274 ret = strcmp(port->hba->krb_realm, cp);
1275
1276 if (ret)
1277 {
1278 /* GSS realm does not match */
1279 elog(DEBUG2,
1280 "GSSAPI realm (%s) and configured realm (%s) don't match",
1281 cp, port->hba->krb_realm);
1282 pfree(princ);
1283 return STATUS_ERROR;
1284 }
1285 }
1286 }
1287 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1288 {
1289 elog(DEBUG2,
1290 "GSSAPI did not return realm but realm matching was requested");
1291 pfree(princ);
1292 return STATUS_ERROR;
1293 }
1294
1295 ret = check_usermap(port->hba->usermap, port->user_name, princ,
1296 pg_krb_caseins_users);
1297
1298 pfree(princ);
1299
1300 return ret;
1301 }
1302 #endif /* ENABLE_GSS */
1303
1304
1305 /*----------------------------------------------------------------
1306 * SSPI authentication system
1307 *----------------------------------------------------------------
1308 */
1309 #ifdef ENABLE_SSPI
1310
1311 /*
1312 * Generate an error for SSPI authentication. The caller should apply
1313 * _() to errmsg to make it translatable.
1314 */
1315 static void
pg_SSPI_error(int severity,const char * errmsg,SECURITY_STATUS r)1316 pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)
1317 {
1318 char sysmsg[256];
1319
1320 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
1321 FORMAT_MESSAGE_FROM_SYSTEM,
1322 NULL, r, 0,
1323 sysmsg, sizeof(sysmsg), NULL) == 0)
1324 ereport(severity,
1325 (errmsg_internal("%s", errmsg),
1326 errdetail_internal("SSPI error %x", (unsigned int) r)));
1327 else
1328 ereport(severity,
1329 (errmsg_internal("%s", errmsg),
1330 errdetail_internal("%s (%x)", sysmsg, (unsigned int) r)));
1331 }
1332
1333 static int
pg_SSPI_recvauth(Port * port)1334 pg_SSPI_recvauth(Port *port)
1335 {
1336 int mtype;
1337 StringInfoData buf;
1338 SECURITY_STATUS r;
1339 CredHandle sspicred;
1340 CtxtHandle *sspictx = NULL,
1341 newctx;
1342 TimeStamp expiry;
1343 ULONG contextattr;
1344 SecBufferDesc inbuf;
1345 SecBufferDesc outbuf;
1346 SecBuffer OutBuffers[1];
1347 SecBuffer InBuffers[1];
1348 HANDLE token;
1349 TOKEN_USER *tokenuser;
1350 DWORD retlen;
1351 char accountname[MAXPGPATH];
1352 char domainname[MAXPGPATH];
1353 DWORD accountnamesize = sizeof(accountname);
1354 DWORD domainnamesize = sizeof(domainname);
1355 SID_NAME_USE accountnameuse;
1356 HMODULE secur32;
1357 char *authn_id;
1358
1359 QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken;
1360
1361 /*
1362 * Acquire a handle to the server credentials.
1363 */
1364 r = AcquireCredentialsHandle(NULL,
1365 "negotiate",
1366 SECPKG_CRED_INBOUND,
1367 NULL,
1368 NULL,
1369 NULL,
1370 NULL,
1371 &sspicred,
1372 &expiry);
1373 if (r != SEC_E_OK)
1374 pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);
1375
1376 /*
1377 * Loop through SSPI message exchange. This exchange can consist of
1378 * multiple messages sent in both directions. First message is always from
1379 * the client. All messages from client to server are password packets
1380 * (type 'p').
1381 */
1382 do
1383 {
1384 pq_startmsgread();
1385 mtype = pq_getbyte();
1386 if (mtype != 'p')
1387 {
1388 if (sspictx != NULL)
1389 {
1390 DeleteSecurityContext(sspictx);
1391 free(sspictx);
1392 }
1393 FreeCredentialsHandle(&sspicred);
1394
1395 /* Only log error if client didn't disconnect. */
1396 if (mtype != EOF)
1397 ereport(ERROR,
1398 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1399 errmsg("expected SSPI response, got message type %d",
1400 mtype)));
1401 return STATUS_ERROR;
1402 }
1403
1404 /* Get the actual SSPI token */
1405 initStringInfo(&buf);
1406 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
1407 {
1408 /* EOF - pq_getmessage already logged error */
1409 pfree(buf.data);
1410 if (sspictx != NULL)
1411 {
1412 DeleteSecurityContext(sspictx);
1413 free(sspictx);
1414 }
1415 FreeCredentialsHandle(&sspicred);
1416 return STATUS_ERROR;
1417 }
1418
1419 /* Map to SSPI style buffer */
1420 inbuf.ulVersion = SECBUFFER_VERSION;
1421 inbuf.cBuffers = 1;
1422 inbuf.pBuffers = InBuffers;
1423 InBuffers[0].pvBuffer = buf.data;
1424 InBuffers[0].cbBuffer = buf.len;
1425 InBuffers[0].BufferType = SECBUFFER_TOKEN;
1426
1427 /* Prepare output buffer */
1428 OutBuffers[0].pvBuffer = NULL;
1429 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
1430 OutBuffers[0].cbBuffer = 0;
1431 outbuf.cBuffers = 1;
1432 outbuf.pBuffers = OutBuffers;
1433 outbuf.ulVersion = SECBUFFER_VERSION;
1434
1435 elog(DEBUG4, "processing received SSPI token of length %u",
1436 (unsigned int) buf.len);
1437
1438 r = AcceptSecurityContext(&sspicred,
1439 sspictx,
1440 &inbuf,
1441 ASC_REQ_ALLOCATE_MEMORY,
1442 SECURITY_NETWORK_DREP,
1443 &newctx,
1444 &outbuf,
1445 &contextattr,
1446 NULL);
1447
1448 /* input buffer no longer used */
1449 pfree(buf.data);
1450
1451 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
1452 {
1453 /*
1454 * Negotiation generated data to be sent to the client.
1455 */
1456 elog(DEBUG4, "sending SSPI response token of length %u",
1457 (unsigned int) outbuf.pBuffers[0].cbBuffer);
1458
1459 port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
1460 port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
1461
1462 sendAuthRequest(port, AUTH_REQ_GSS_CONT,
1463 port->gss->outbuf.value, port->gss->outbuf.length);
1464
1465 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
1466 }
1467
1468 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
1469 {
1470 if (sspictx != NULL)
1471 {
1472 DeleteSecurityContext(sspictx);
1473 free(sspictx);
1474 }
1475 FreeCredentialsHandle(&sspicred);
1476 pg_SSPI_error(ERROR,
1477 _("could not accept SSPI security context"), r);
1478 }
1479
1480 /*
1481 * Overwrite the current context with the one we just received. If
1482 * sspictx is NULL it was the first loop and we need to allocate a
1483 * buffer for it. On subsequent runs, we can just overwrite the buffer
1484 * contents since the size does not change.
1485 */
1486 if (sspictx == NULL)
1487 {
1488 sspictx = malloc(sizeof(CtxtHandle));
1489 if (sspictx == NULL)
1490 ereport(ERROR,
1491 (errmsg("out of memory")));
1492 }
1493
1494 memcpy(sspictx, &newctx, sizeof(CtxtHandle));
1495
1496 if (r == SEC_I_CONTINUE_NEEDED)
1497 elog(DEBUG4, "SSPI continue needed");
1498
1499 } while (r == SEC_I_CONTINUE_NEEDED);
1500
1501
1502 /*
1503 * Release service principal credentials
1504 */
1505 FreeCredentialsHandle(&sspicred);
1506
1507
1508 /*
1509 * SEC_E_OK indicates that authentication is now complete.
1510 *
1511 * Get the name of the user that authenticated, and compare it to the pg
1512 * username that was specified for the connection.
1513 *
1514 * MingW is missing the export for QuerySecurityContextToken in the
1515 * secur32 library, so we have to load it dynamically.
1516 */
1517
1518 secur32 = LoadLibrary("SECUR32.DLL");
1519 if (secur32 == NULL)
1520 ereport(ERROR,
1521 (errmsg("could not load library \"%s\": error code %lu",
1522 "SECUR32.DLL", GetLastError())));
1523
1524 _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN) (pg_funcptr_t)
1525 GetProcAddress(secur32, "QuerySecurityContextToken");
1526 if (_QuerySecurityContextToken == NULL)
1527 {
1528 FreeLibrary(secur32);
1529 ereport(ERROR,
1530 (errmsg_internal("could not locate QuerySecurityContextToken in secur32.dll: error code %lu",
1531 GetLastError())));
1532 }
1533
1534 r = (_QuerySecurityContextToken) (sspictx, &token);
1535 if (r != SEC_E_OK)
1536 {
1537 FreeLibrary(secur32);
1538 pg_SSPI_error(ERROR,
1539 _("could not get token from SSPI security context"), r);
1540 }
1541
1542 FreeLibrary(secur32);
1543
1544 /*
1545 * No longer need the security context, everything from here on uses the
1546 * token instead.
1547 */
1548 DeleteSecurityContext(sspictx);
1549 free(sspictx);
1550
1551 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
1552 ereport(ERROR,
1553 (errmsg_internal("could not get token information buffer size: error code %lu",
1554 GetLastError())));
1555
1556 tokenuser = malloc(retlen);
1557 if (tokenuser == NULL)
1558 ereport(ERROR,
1559 (errmsg("out of memory")));
1560
1561 if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
1562 ereport(ERROR,
1563 (errmsg_internal("could not get token information: error code %lu",
1564 GetLastError())));
1565
1566 CloseHandle(token);
1567
1568 if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
1569 domainname, &domainnamesize, &accountnameuse))
1570 ereport(ERROR,
1571 (errmsg_internal("could not look up account SID: error code %lu",
1572 GetLastError())));
1573
1574 free(tokenuser);
1575
1576 if (!port->hba->compat_realm)
1577 {
1578 int status = pg_SSPI_make_upn(accountname, sizeof(accountname),
1579 domainname, sizeof(domainname),
1580 port->hba->upn_username);
1581
1582 if (status != STATUS_OK)
1583 /* Error already reported from pg_SSPI_make_upn */
1584 return status;
1585 }
1586
1587 /*
1588 * We have all of the information necessary to construct the authenticated
1589 * identity. Set it now, rather than waiting for check_usermap below,
1590 * because authentication has already succeeded and we want the log file
1591 * to reflect that.
1592 */
1593 if (port->hba->compat_realm)
1594 {
1595 /* SAM-compatible format. */
1596 authn_id = psprintf("%s\\%s", domainname, accountname);
1597 }
1598 else
1599 {
1600 /* Kerberos principal format. */
1601 authn_id = psprintf("%s@%s", accountname, domainname);
1602 }
1603
1604 set_authn_id(port, authn_id);
1605 pfree(authn_id);
1606
1607 /*
1608 * Compare realm/domain if requested. In SSPI, always compare case
1609 * insensitive.
1610 */
1611 if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1612 {
1613 if (pg_strcasecmp(port->hba->krb_realm, domainname) != 0)
1614 {
1615 elog(DEBUG2,
1616 "SSPI domain (%s) and configured domain (%s) don't match",
1617 domainname, port->hba->krb_realm);
1618
1619 return STATUS_ERROR;
1620 }
1621 }
1622
1623 /*
1624 * We have the username (without domain/realm) in accountname, compare to
1625 * the supplied value. In SSPI, always compare case insensitive.
1626 *
1627 * If set to include realm, append it in <username>@<realm> format.
1628 */
1629 if (port->hba->include_realm)
1630 {
1631 char *namebuf;
1632 int retval;
1633
1634 namebuf = psprintf("%s@%s", accountname, domainname);
1635 retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
1636 pfree(namebuf);
1637 return retval;
1638 }
1639 else
1640 return check_usermap(port->hba->usermap, port->user_name, accountname, true);
1641 }
1642
1643 /*
1644 * Replaces the domainname with the Kerberos realm name,
1645 * and optionally the accountname with the Kerberos user name.
1646 */
1647 static int
pg_SSPI_make_upn(char * accountname,size_t accountnamesize,char * domainname,size_t domainnamesize,bool update_accountname)1648 pg_SSPI_make_upn(char *accountname,
1649 size_t accountnamesize,
1650 char *domainname,
1651 size_t domainnamesize,
1652 bool update_accountname)
1653 {
1654 char *samname;
1655 char *upname = NULL;
1656 char *p = NULL;
1657 ULONG upnamesize = 0;
1658 size_t upnamerealmsize;
1659 BOOLEAN res;
1660
1661 /*
1662 * Build SAM name (DOMAIN\user), then translate to UPN
1663 * (user@kerberos.realm). The realm name is returned in lower case, but
1664 * that is fine because in SSPI auth, string comparisons are always
1665 * case-insensitive.
1666 */
1667
1668 samname = psprintf("%s\\%s", domainname, accountname);
1669 res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
1670 NULL, &upnamesize);
1671
1672 if ((!res && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1673 || upnamesize == 0)
1674 {
1675 pfree(samname);
1676 ereport(LOG,
1677 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1678 errmsg("could not translate name")));
1679 return STATUS_ERROR;
1680 }
1681
1682 /* upnamesize includes the terminating NUL. */
1683 upname = palloc(upnamesize);
1684
1685 res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
1686 upname, &upnamesize);
1687
1688 pfree(samname);
1689 if (res)
1690 p = strchr(upname, '@');
1691
1692 if (!res || p == NULL)
1693 {
1694 pfree(upname);
1695 ereport(LOG,
1696 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1697 errmsg("could not translate name")));
1698 return STATUS_ERROR;
1699 }
1700
1701 /* Length of realm name after the '@', including the NUL. */
1702 upnamerealmsize = upnamesize - (p - upname + 1);
1703
1704 /* Replace domainname with realm name. */
1705 if (upnamerealmsize > domainnamesize)
1706 {
1707 pfree(upname);
1708 ereport(LOG,
1709 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1710 errmsg("realm name too long")));
1711 return STATUS_ERROR;
1712 }
1713
1714 /* Length is now safe. */
1715 strcpy(domainname, p + 1);
1716
1717 /* Replace account name as well (in case UPN != SAM)? */
1718 if (update_accountname)
1719 {
1720 if ((p - upname + 1) > accountnamesize)
1721 {
1722 pfree(upname);
1723 ereport(LOG,
1724 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1725 errmsg("translated account name too long")));
1726 return STATUS_ERROR;
1727 }
1728
1729 *p = 0;
1730 strcpy(accountname, upname);
1731 }
1732
1733 pfree(upname);
1734 return STATUS_OK;
1735 }
1736 #endif /* ENABLE_SSPI */
1737
1738
1739
1740 /*----------------------------------------------------------------
1741 * Ident authentication system
1742 *----------------------------------------------------------------
1743 */
1744
1745 /*
1746 * Parse the string "*ident_response" as a response from a query to an Ident
1747 * server. If it's a normal response indicating a user name, return true
1748 * and store the user name at *ident_user. If it's anything else,
1749 * return false.
1750 */
1751 static bool
interpret_ident_response(const char * ident_response,char * ident_user)1752 interpret_ident_response(const char *ident_response,
1753 char *ident_user)
1754 {
1755 const char *cursor = ident_response; /* Cursor into *ident_response */
1756
1757 /*
1758 * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1759 */
1760 if (strlen(ident_response) < 2)
1761 return false;
1762 else if (ident_response[strlen(ident_response) - 2] != '\r')
1763 return false;
1764 else
1765 {
1766 while (*cursor != ':' && *cursor != '\r')
1767 cursor++; /* skip port field */
1768
1769 if (*cursor != ':')
1770 return false;
1771 else
1772 {
1773 /* We're positioned to colon before response type field */
1774 char response_type[80];
1775 int i; /* Index into *response_type */
1776
1777 cursor++; /* Go over colon */
1778 while (pg_isblank(*cursor))
1779 cursor++; /* skip blanks */
1780 i = 0;
1781 while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1782 i < (int) (sizeof(response_type) - 1))
1783 response_type[i++] = *cursor++;
1784 response_type[i] = '\0';
1785 while (pg_isblank(*cursor))
1786 cursor++; /* skip blanks */
1787 if (strcmp(response_type, "USERID") != 0)
1788 return false;
1789 else
1790 {
1791 /*
1792 * It's a USERID response. Good. "cursor" should be pointing
1793 * to the colon that precedes the operating system type.
1794 */
1795 if (*cursor != ':')
1796 return false;
1797 else
1798 {
1799 cursor++; /* Go over colon */
1800 /* Skip over operating system field. */
1801 while (*cursor != ':' && *cursor != '\r')
1802 cursor++;
1803 if (*cursor != ':')
1804 return false;
1805 else
1806 {
1807 int i; /* Index into *ident_user */
1808
1809 cursor++; /* Go over colon */
1810 while (pg_isblank(*cursor))
1811 cursor++; /* skip blanks */
1812 /* Rest of line is user name. Copy it over. */
1813 i = 0;
1814 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1815 ident_user[i++] = *cursor++;
1816 ident_user[i] = '\0';
1817 return true;
1818 }
1819 }
1820 }
1821 }
1822 }
1823 }
1824
1825
1826 /*
1827 * Talk to the ident server on "remote_addr" and find out who
1828 * owns the tcp connection to "local_addr"
1829 * If the username is successfully retrieved, check the usermap.
1830 *
1831 * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if the
1832 * latch was set would improve the responsiveness to timeouts/cancellations.
1833 */
1834 static int
ident_inet(hbaPort * port)1835 ident_inet(hbaPort *port)
1836 {
1837 const SockAddr remote_addr = port->raddr;
1838 const SockAddr local_addr = port->laddr;
1839 char ident_user[IDENT_USERNAME_MAX + 1];
1840 pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1841 int rc; /* Return code from a locally called function */
1842 bool ident_return;
1843 char remote_addr_s[NI_MAXHOST];
1844 char remote_port[NI_MAXSERV];
1845 char local_addr_s[NI_MAXHOST];
1846 char local_port[NI_MAXSERV];
1847 char ident_port[NI_MAXSERV];
1848 char ident_query[80];
1849 char ident_response[80 + IDENT_USERNAME_MAX];
1850 struct addrinfo *ident_serv = NULL,
1851 *la = NULL,
1852 hints;
1853
1854 /*
1855 * Might look a little weird to first convert it to text and then back to
1856 * sockaddr, but it's protocol independent.
1857 */
1858 pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1859 remote_addr_s, sizeof(remote_addr_s),
1860 remote_port, sizeof(remote_port),
1861 NI_NUMERICHOST | NI_NUMERICSERV);
1862 pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1863 local_addr_s, sizeof(local_addr_s),
1864 local_port, sizeof(local_port),
1865 NI_NUMERICHOST | NI_NUMERICSERV);
1866
1867 snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1868 hints.ai_flags = AI_NUMERICHOST;
1869 hints.ai_family = remote_addr.addr.ss_family;
1870 hints.ai_socktype = SOCK_STREAM;
1871 hints.ai_protocol = 0;
1872 hints.ai_addrlen = 0;
1873 hints.ai_canonname = NULL;
1874 hints.ai_addr = NULL;
1875 hints.ai_next = NULL;
1876 rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1877 if (rc || !ident_serv)
1878 {
1879 /* we don't expect this to happen */
1880 ident_return = false;
1881 goto ident_inet_done;
1882 }
1883
1884 hints.ai_flags = AI_NUMERICHOST;
1885 hints.ai_family = local_addr.addr.ss_family;
1886 hints.ai_socktype = SOCK_STREAM;
1887 hints.ai_protocol = 0;
1888 hints.ai_addrlen = 0;
1889 hints.ai_canonname = NULL;
1890 hints.ai_addr = NULL;
1891 hints.ai_next = NULL;
1892 rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1893 if (rc || !la)
1894 {
1895 /* we don't expect this to happen */
1896 ident_return = false;
1897 goto ident_inet_done;
1898 }
1899
1900 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1901 ident_serv->ai_protocol);
1902 if (sock_fd == PGINVALID_SOCKET)
1903 {
1904 ereport(LOG,
1905 (errcode_for_socket_access(),
1906 errmsg("could not create socket for Ident connection: %m")));
1907 ident_return = false;
1908 goto ident_inet_done;
1909 }
1910
1911 /*
1912 * Bind to the address which the client originally contacted, otherwise
1913 * the ident server won't be able to match up the right connection. This
1914 * is necessary if the PostgreSQL server is running on an IP alias.
1915 */
1916 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1917 if (rc != 0)
1918 {
1919 ereport(LOG,
1920 (errcode_for_socket_access(),
1921 errmsg("could not bind to local address \"%s\": %m",
1922 local_addr_s)));
1923 ident_return = false;
1924 goto ident_inet_done;
1925 }
1926
1927 rc = connect(sock_fd, ident_serv->ai_addr,
1928 ident_serv->ai_addrlen);
1929 if (rc != 0)
1930 {
1931 ereport(LOG,
1932 (errcode_for_socket_access(),
1933 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1934 remote_addr_s, ident_port)));
1935 ident_return = false;
1936 goto ident_inet_done;
1937 }
1938
1939 /* The query we send to the Ident server */
1940 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1941 remote_port, local_port);
1942
1943 /* loop in case send is interrupted */
1944 do
1945 {
1946 CHECK_FOR_INTERRUPTS();
1947
1948 rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1949 } while (rc < 0 && errno == EINTR);
1950
1951 if (rc < 0)
1952 {
1953 ereport(LOG,
1954 (errcode_for_socket_access(),
1955 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1956 remote_addr_s, ident_port)));
1957 ident_return = false;
1958 goto ident_inet_done;
1959 }
1960
1961 do
1962 {
1963 CHECK_FOR_INTERRUPTS();
1964
1965 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1966 } while (rc < 0 && errno == EINTR);
1967
1968 if (rc < 0)
1969 {
1970 ereport(LOG,
1971 (errcode_for_socket_access(),
1972 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1973 remote_addr_s, ident_port)));
1974 ident_return = false;
1975 goto ident_inet_done;
1976 }
1977
1978 ident_response[rc] = '\0';
1979 ident_return = interpret_ident_response(ident_response, ident_user);
1980 if (!ident_return)
1981 ereport(LOG,
1982 (errmsg("invalidly formatted response from Ident server: \"%s\"",
1983 ident_response)));
1984
1985 ident_inet_done:
1986 if (sock_fd != PGINVALID_SOCKET)
1987 closesocket(sock_fd);
1988 if (ident_serv)
1989 pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1990 if (la)
1991 pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1992
1993 if (ident_return)
1994 {
1995 /*
1996 * Success! Store the identity, then check the usermap. Note that
1997 * setting the authenticated identity is done before checking the
1998 * usermap, because at this point authentication has succeeded.
1999 */
2000 set_authn_id(port, ident_user);
2001 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
2002 }
2003 return STATUS_ERROR;
2004 }
2005
2006
2007 /*----------------------------------------------------------------
2008 * Peer authentication system
2009 *----------------------------------------------------------------
2010 */
2011
2012 /*
2013 * Ask kernel about the credentials of the connecting process,
2014 * determine the symbolic name of the corresponding user, and check
2015 * if valid per the usermap.
2016 *
2017 * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
2018 */
2019 static int
auth_peer(hbaPort * port)2020 auth_peer(hbaPort *port)
2021 {
2022 uid_t uid;
2023 gid_t gid;
2024 #ifndef WIN32
2025 struct passwd *pw;
2026 int ret;
2027 #endif
2028
2029 if (getpeereid(port->sock, &uid, &gid) != 0)
2030 {
2031 /* Provide special error message if getpeereid is a stub */
2032 if (errno == ENOSYS)
2033 ereport(LOG,
2034 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2035 errmsg("peer authentication is not supported on this platform")));
2036 else
2037 ereport(LOG,
2038 (errcode_for_socket_access(),
2039 errmsg("could not get peer credentials: %m")));
2040 return STATUS_ERROR;
2041 }
2042
2043 #ifndef WIN32
2044 errno = 0; /* clear errno before call */
2045 pw = getpwuid(uid);
2046 if (!pw)
2047 {
2048 int save_errno = errno;
2049
2050 ereport(LOG,
2051 (errmsg("could not look up local user ID %ld: %s",
2052 (long) uid,
2053 save_errno ? strerror(save_errno) : _("user does not exist"))));
2054 return STATUS_ERROR;
2055 }
2056
2057 /*
2058 * Make a copy of static getpw*() result area; this is our authenticated
2059 * identity. Set it before calling check_usermap, because authentication
2060 * has already succeeded and we want the log file to reflect that.
2061 */
2062 set_authn_id(port, pw->pw_name);
2063
2064 ret = check_usermap(port->hba->usermap, port->user_name, port->authn_id, false);
2065
2066 return ret;
2067 #else
2068 /* should have failed with ENOSYS above */
2069 Assert(false);
2070 return STATUS_ERROR;
2071 #endif
2072 }
2073
2074
2075 /*----------------------------------------------------------------
2076 * PAM authentication system
2077 *----------------------------------------------------------------
2078 */
2079 #ifdef USE_PAM
2080
2081 /*
2082 * PAM conversation function
2083 */
2084
2085 static int
pam_passwd_conv_proc(int num_msg,const struct pam_message ** msg,struct pam_response ** resp,void * appdata_ptr)2086 pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
2087 struct pam_response **resp, void *appdata_ptr)
2088 {
2089 const char *passwd;
2090 struct pam_response *reply;
2091 int i;
2092
2093 if (appdata_ptr)
2094 passwd = (char *) appdata_ptr;
2095 else
2096 {
2097 /*
2098 * Workaround for Solaris 2.6 where the PAM library is broken and does
2099 * not pass appdata_ptr to the conversation routine
2100 */
2101 passwd = pam_passwd;
2102 }
2103
2104 *resp = NULL; /* in case of error exit */
2105
2106 if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)
2107 return PAM_CONV_ERR;
2108
2109 /*
2110 * Explicitly not using palloc here - PAM will free this memory in
2111 * pam_end()
2112 */
2113 if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
2114 {
2115 ereport(LOG,
2116 (errcode(ERRCODE_OUT_OF_MEMORY),
2117 errmsg("out of memory")));
2118 return PAM_CONV_ERR;
2119 }
2120
2121 for (i = 0; i < num_msg; i++)
2122 {
2123 switch (msg[i]->msg_style)
2124 {
2125 case PAM_PROMPT_ECHO_OFF:
2126 if (strlen(passwd) == 0)
2127 {
2128 /*
2129 * Password wasn't passed to PAM the first time around -
2130 * let's go ask the client to send a password, which we
2131 * then stuff into PAM.
2132 */
2133 sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD, NULL, 0);
2134 passwd = recv_password_packet(pam_port_cludge);
2135 if (passwd == NULL)
2136 {
2137 /*
2138 * Client didn't want to send password. We
2139 * intentionally do not log anything about this,
2140 * either here or at higher levels.
2141 */
2142 pam_no_password = true;
2143 goto fail;
2144 }
2145 }
2146 if ((reply[i].resp = strdup(passwd)) == NULL)
2147 goto fail;
2148 reply[i].resp_retcode = PAM_SUCCESS;
2149 break;
2150 case PAM_ERROR_MSG:
2151 ereport(LOG,
2152 (errmsg("error from underlying PAM layer: %s",
2153 msg[i]->msg)));
2154 /* FALL THROUGH */
2155 case PAM_TEXT_INFO:
2156 /* we don't bother to log TEXT_INFO messages */
2157 if ((reply[i].resp = strdup("")) == NULL)
2158 goto fail;
2159 reply[i].resp_retcode = PAM_SUCCESS;
2160 break;
2161 default:
2162 ereport(LOG,
2163 (errmsg("unsupported PAM conversation %d/\"%s\"",
2164 msg[i]->msg_style,
2165 msg[i]->msg ? msg[i]->msg : "(none)")));
2166 goto fail;
2167 }
2168 }
2169
2170 *resp = reply;
2171 return PAM_SUCCESS;
2172
2173 fail:
2174 /* free up whatever we allocated */
2175 for (i = 0; i < num_msg; i++)
2176 {
2177 if (reply[i].resp != NULL)
2178 free(reply[i].resp);
2179 }
2180 free(reply);
2181
2182 return PAM_CONV_ERR;
2183 }
2184
2185
2186 /*
2187 * Check authentication against PAM.
2188 */
2189 static int
CheckPAMAuth(Port * port,const char * user,const char * password)2190 CheckPAMAuth(Port *port, const char *user, const char *password)
2191 {
2192 int retval;
2193 pam_handle_t *pamh = NULL;
2194
2195 /*
2196 * We can't entirely rely on PAM to pass through appdata --- it appears
2197 * not to work on at least Solaris 2.6. So use these ugly static
2198 * variables instead.
2199 */
2200 pam_passwd = password;
2201 pam_port_cludge = port;
2202 pam_no_password = false;
2203
2204 /*
2205 * Set the application data portion of the conversation struct. This is
2206 * later used inside the PAM conversation to pass the password to the
2207 * authentication module.
2208 */
2209 pam_passw_conv.appdata_ptr = unconstify(char *, password); /* from password above,
2210 * not allocated */
2211
2212 /* Optionally, one can set the service name in pg_hba.conf */
2213 if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
2214 retval = pam_start(port->hba->pamservice, "pgsql@",
2215 &pam_passw_conv, &pamh);
2216 else
2217 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
2218 &pam_passw_conv, &pamh);
2219
2220 if (retval != PAM_SUCCESS)
2221 {
2222 ereport(LOG,
2223 (errmsg("could not create PAM authenticator: %s",
2224 pam_strerror(pamh, retval))));
2225 pam_passwd = NULL; /* Unset pam_passwd */
2226 return STATUS_ERROR;
2227 }
2228
2229 retval = pam_set_item(pamh, PAM_USER, user);
2230
2231 if (retval != PAM_SUCCESS)
2232 {
2233 ereport(LOG,
2234 (errmsg("pam_set_item(PAM_USER) failed: %s",
2235 pam_strerror(pamh, retval))));
2236 pam_passwd = NULL; /* Unset pam_passwd */
2237 return STATUS_ERROR;
2238 }
2239
2240 if (port->hba->conntype != ctLocal)
2241 {
2242 char hostinfo[NI_MAXHOST];
2243 int flags;
2244
2245 if (port->hba->pam_use_hostname)
2246 flags = 0;
2247 else
2248 flags = NI_NUMERICHOST | NI_NUMERICSERV;
2249
2250 retval = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
2251 hostinfo, sizeof(hostinfo), NULL, 0,
2252 flags);
2253 if (retval != 0)
2254 {
2255 ereport(WARNING,
2256 (errmsg_internal("pg_getnameinfo_all() failed: %s",
2257 gai_strerror(retval))));
2258 return STATUS_ERROR;
2259 }
2260
2261 retval = pam_set_item(pamh, PAM_RHOST, hostinfo);
2262
2263 if (retval != PAM_SUCCESS)
2264 {
2265 ereport(LOG,
2266 (errmsg("pam_set_item(PAM_RHOST) failed: %s",
2267 pam_strerror(pamh, retval))));
2268 pam_passwd = NULL;
2269 return STATUS_ERROR;
2270 }
2271 }
2272
2273 retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
2274
2275 if (retval != PAM_SUCCESS)
2276 {
2277 ereport(LOG,
2278 (errmsg("pam_set_item(PAM_CONV) failed: %s",
2279 pam_strerror(pamh, retval))));
2280 pam_passwd = NULL; /* Unset pam_passwd */
2281 return STATUS_ERROR;
2282 }
2283
2284 retval = pam_authenticate(pamh, 0);
2285
2286 if (retval != PAM_SUCCESS)
2287 {
2288 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2289 if (!pam_no_password)
2290 ereport(LOG,
2291 (errmsg("pam_authenticate failed: %s",
2292 pam_strerror(pamh, retval))));
2293 pam_passwd = NULL; /* Unset pam_passwd */
2294 return pam_no_password ? STATUS_EOF : STATUS_ERROR;
2295 }
2296
2297 retval = pam_acct_mgmt(pamh, 0);
2298
2299 if (retval != PAM_SUCCESS)
2300 {
2301 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2302 if (!pam_no_password)
2303 ereport(LOG,
2304 (errmsg("pam_acct_mgmt failed: %s",
2305 pam_strerror(pamh, retval))));
2306 pam_passwd = NULL; /* Unset pam_passwd */
2307 return pam_no_password ? STATUS_EOF : STATUS_ERROR;
2308 }
2309
2310 retval = pam_end(pamh, retval);
2311
2312 if (retval != PAM_SUCCESS)
2313 {
2314 ereport(LOG,
2315 (errmsg("could not release PAM authenticator: %s",
2316 pam_strerror(pamh, retval))));
2317 }
2318
2319 pam_passwd = NULL; /* Unset pam_passwd */
2320
2321 if (retval == PAM_SUCCESS)
2322 set_authn_id(port, user);
2323
2324 return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
2325 }
2326 #endif /* USE_PAM */
2327
2328
2329 /*----------------------------------------------------------------
2330 * BSD authentication system
2331 *----------------------------------------------------------------
2332 */
2333 #ifdef USE_BSD_AUTH
2334 static int
CheckBSDAuth(Port * port,char * user)2335 CheckBSDAuth(Port *port, char *user)
2336 {
2337 char *passwd;
2338 int retval;
2339
2340 /* Send regular password request to client, and get the response */
2341 sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
2342
2343 passwd = recv_password_packet(port);
2344 if (passwd == NULL)
2345 return STATUS_EOF;
2346
2347 /*
2348 * Ask the BSD auth system to verify password. Note that auth_userokay
2349 * will overwrite the password string with zeroes, but it's just a
2350 * temporary string so we don't care.
2351 */
2352 retval = auth_userokay(user, NULL, "auth-postgresql", passwd);
2353
2354 pfree(passwd);
2355
2356 if (!retval)
2357 return STATUS_ERROR;
2358
2359 set_authn_id(port, user);
2360 return STATUS_OK;
2361 }
2362 #endif /* USE_BSD_AUTH */
2363
2364
2365 /*----------------------------------------------------------------
2366 * LDAP authentication system
2367 *----------------------------------------------------------------
2368 */
2369 #ifdef USE_LDAP
2370
2371 static int errdetail_for_ldap(LDAP *ldap);
2372
2373 /*
2374 * Initialize a connection to the LDAP server, including setting up
2375 * TLS if requested.
2376 */
2377 static int
InitializeLDAPConnection(Port * port,LDAP ** ldap)2378 InitializeLDAPConnection(Port *port, LDAP **ldap)
2379 {
2380 const char *scheme;
2381 int ldapversion = LDAP_VERSION3;
2382 int r;
2383
2384 scheme = port->hba->ldapscheme;
2385 if (scheme == NULL)
2386 scheme = "ldap";
2387 #ifdef WIN32
2388 if (strcmp(scheme, "ldaps") == 0)
2389 *ldap = ldap_sslinit(port->hba->ldapserver, port->hba->ldapport, 1);
2390 else
2391 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2392 if (!*ldap)
2393 {
2394 ereport(LOG,
2395 (errmsg("could not initialize LDAP: error code %d",
2396 (int) LdapGetLastError())));
2397
2398 return STATUS_ERROR;
2399 }
2400 #else
2401 #ifdef HAVE_LDAP_INITIALIZE
2402
2403 /*
2404 * OpenLDAP provides a non-standard extension ldap_initialize() that takes
2405 * a list of URIs, allowing us to request "ldaps" instead of "ldap". It
2406 * also provides ldap_domain2hostlist() to find LDAP servers automatically
2407 * using DNS SRV. They were introduced in the same version, so for now we
2408 * don't have an extra configure check for the latter.
2409 */
2410 {
2411 StringInfoData uris;
2412 char *hostlist = NULL;
2413 char *p;
2414 bool append_port;
2415
2416 /* We'll build a space-separated scheme://hostname:port list here */
2417 initStringInfo(&uris);
2418
2419 /*
2420 * If pg_hba.conf provided no hostnames, we can ask OpenLDAP to try to
2421 * find some by extracting a domain name from the base DN and looking
2422 * up DSN SRV records for _ldap._tcp.<domain>.
2423 */
2424 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2425 {
2426 char *domain;
2427
2428 /* ou=blah,dc=foo,dc=bar -> foo.bar */
2429 if (ldap_dn2domain(port->hba->ldapbasedn, &domain))
2430 {
2431 ereport(LOG,
2432 (errmsg("could not extract domain name from ldapbasedn")));
2433 return STATUS_ERROR;
2434 }
2435
2436 /* Look up a list of LDAP server hosts and port numbers */
2437 if (ldap_domain2hostlist(domain, &hostlist))
2438 {
2439 ereport(LOG,
2440 (errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",
2441 domain),
2442 (errhint("Set an LDAP server name explicitly."))));
2443 ldap_memfree(domain);
2444 return STATUS_ERROR;
2445 }
2446 ldap_memfree(domain);
2447
2448 /* We have a space-separated list of host:port entries */
2449 p = hostlist;
2450 append_port = false;
2451 }
2452 else
2453 {
2454 /* We have a space-separated list of hosts from pg_hba.conf */
2455 p = port->hba->ldapserver;
2456 append_port = true;
2457 }
2458
2459 /* Convert the list of host[:port] entries to full URIs */
2460 do
2461 {
2462 size_t size;
2463
2464 /* Find the span of the next entry */
2465 size = strcspn(p, " ");
2466
2467 /* Append a space separator if this isn't the first URI */
2468 if (uris.len > 0)
2469 appendStringInfoChar(&uris, ' ');
2470
2471 /* Append scheme://host:port */
2472 appendStringInfoString(&uris, scheme);
2473 appendStringInfoString(&uris, "://");
2474 appendBinaryStringInfo(&uris, p, size);
2475 if (append_port)
2476 appendStringInfo(&uris, ":%d", port->hba->ldapport);
2477
2478 /* Step over this entry and any number of trailing spaces */
2479 p += size;
2480 while (*p == ' ')
2481 ++p;
2482 } while (*p);
2483
2484 /* Free memory from OpenLDAP if we looked up SRV records */
2485 if (hostlist)
2486 ldap_memfree(hostlist);
2487
2488 /* Finally, try to connect using the URI list */
2489 r = ldap_initialize(ldap, uris.data);
2490 pfree(uris.data);
2491 if (r != LDAP_SUCCESS)
2492 {
2493 ereport(LOG,
2494 (errmsg("could not initialize LDAP: %s",
2495 ldap_err2string(r))));
2496
2497 return STATUS_ERROR;
2498 }
2499 }
2500 #else
2501 if (strcmp(scheme, "ldaps") == 0)
2502 {
2503 ereport(LOG,
2504 (errmsg("ldaps not supported with this LDAP library")));
2505
2506 return STATUS_ERROR;
2507 }
2508 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2509 if (!*ldap)
2510 {
2511 ereport(LOG,
2512 (errmsg("could not initialize LDAP: %m")));
2513
2514 return STATUS_ERROR;
2515 }
2516 #endif
2517 #endif
2518
2519 if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
2520 {
2521 ereport(LOG,
2522 (errmsg("could not set LDAP protocol version: %s",
2523 ldap_err2string(r)),
2524 errdetail_for_ldap(*ldap)));
2525 ldap_unbind(*ldap);
2526 return STATUS_ERROR;
2527 }
2528
2529 if (port->hba->ldaptls)
2530 {
2531 #ifndef WIN32
2532 if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
2533 #else
2534 static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
2535
2536 if (_ldap_start_tls_sA == NULL)
2537 {
2538 /*
2539 * Need to load this function dynamically because it may not exist
2540 * on Windows, and causes a load error for the whole exe if
2541 * referenced.
2542 */
2543 HANDLE ldaphandle;
2544
2545 ldaphandle = LoadLibrary("WLDAP32.DLL");
2546 if (ldaphandle == NULL)
2547 {
2548 /*
2549 * should never happen since we import other files from
2550 * wldap32, but check anyway
2551 */
2552 ereport(LOG,
2553 (errmsg("could not load library \"%s\": error code %lu",
2554 "WLDAP32.DLL", GetLastError())));
2555 ldap_unbind(*ldap);
2556 return STATUS_ERROR;
2557 }
2558 _ldap_start_tls_sA = (__ldap_start_tls_sA) (pg_funcptr_t) GetProcAddress(ldaphandle, "ldap_start_tls_sA");
2559 if (_ldap_start_tls_sA == NULL)
2560 {
2561 ereport(LOG,
2562 (errmsg("could not load function _ldap_start_tls_sA in wldap32.dll"),
2563 errdetail("LDAP over SSL is not supported on this platform.")));
2564 ldap_unbind(*ldap);
2565 FreeLibrary(ldaphandle);
2566 return STATUS_ERROR;
2567 }
2568
2569 /*
2570 * Leak LDAP handle on purpose, because we need the library to
2571 * stay open. This is ok because it will only ever be leaked once
2572 * per process and is automatically cleaned up on process exit.
2573 */
2574 }
2575 if ((r = _ldap_start_tls_sA(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
2576 #endif
2577 {
2578 ereport(LOG,
2579 (errmsg("could not start LDAP TLS session: %s",
2580 ldap_err2string(r)),
2581 errdetail_for_ldap(*ldap)));
2582 ldap_unbind(*ldap);
2583 return STATUS_ERROR;
2584 }
2585 }
2586
2587 return STATUS_OK;
2588 }
2589
2590 /* Placeholders recognized by FormatSearchFilter. For now just one. */
2591 #define LPH_USERNAME "$username"
2592 #define LPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)
2593
2594 /* Not all LDAP implementations define this. */
2595 #ifndef LDAP_NO_ATTRS
2596 #define LDAP_NO_ATTRS "1.1"
2597 #endif
2598
2599 /* Not all LDAP implementations define this. */
2600 #ifndef LDAPS_PORT
2601 #define LDAPS_PORT 636
2602 #endif
2603
2604 /*
2605 * Return a newly allocated C string copied from "pattern" with all
2606 * occurrences of the placeholder "$username" replaced with "user_name".
2607 */
2608 static char *
FormatSearchFilter(const char * pattern,const char * user_name)2609 FormatSearchFilter(const char *pattern, const char *user_name)
2610 {
2611 StringInfoData output;
2612
2613 initStringInfo(&output);
2614 while (*pattern != '\0')
2615 {
2616 if (strncmp(pattern, LPH_USERNAME, LPH_USERNAME_LEN) == 0)
2617 {
2618 appendStringInfoString(&output, user_name);
2619 pattern += LPH_USERNAME_LEN;
2620 }
2621 else
2622 appendStringInfoChar(&output, *pattern++);
2623 }
2624
2625 return output.data;
2626 }
2627
2628 /*
2629 * Perform LDAP authentication
2630 */
2631 static int
CheckLDAPAuth(Port * port)2632 CheckLDAPAuth(Port *port)
2633 {
2634 char *passwd;
2635 LDAP *ldap;
2636 int r;
2637 char *fulluser;
2638 const char *server_name;
2639
2640 #ifdef HAVE_LDAP_INITIALIZE
2641
2642 /*
2643 * For OpenLDAP, allow empty hostname if we have a basedn. We'll look for
2644 * servers with DNS SRV records via OpenLDAP library facilities.
2645 */
2646 if ((!port->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&
2647 (!port->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))
2648 {
2649 ereport(LOG,
2650 (errmsg("LDAP server not specified, and no ldapbasedn")));
2651 return STATUS_ERROR;
2652 }
2653 #else
2654 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2655 {
2656 ereport(LOG,
2657 (errmsg("LDAP server not specified")));
2658 return STATUS_ERROR;
2659 }
2660 #endif
2661
2662 /*
2663 * If we're using SRV records, we don't have a server name so we'll just
2664 * show an empty string in error messages.
2665 */
2666 server_name = port->hba->ldapserver ? port->hba->ldapserver : "";
2667
2668 if (port->hba->ldapport == 0)
2669 {
2670 if (port->hba->ldapscheme != NULL &&
2671 strcmp(port->hba->ldapscheme, "ldaps") == 0)
2672 port->hba->ldapport = LDAPS_PORT;
2673 else
2674 port->hba->ldapport = LDAP_PORT;
2675 }
2676
2677 sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
2678
2679 passwd = recv_password_packet(port);
2680 if (passwd == NULL)
2681 return STATUS_EOF; /* client wouldn't send password */
2682
2683 if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
2684 {
2685 /* Error message already sent */
2686 pfree(passwd);
2687 return STATUS_ERROR;
2688 }
2689
2690 if (port->hba->ldapbasedn)
2691 {
2692 /*
2693 * First perform an LDAP search to find the DN for the user we are
2694 * trying to log in as.
2695 */
2696 char *filter;
2697 LDAPMessage *search_message;
2698 LDAPMessage *entry;
2699 char *attributes[] = {LDAP_NO_ATTRS, NULL};
2700 char *dn;
2701 char *c;
2702 int count;
2703
2704 /*
2705 * Disallow any characters that we would otherwise need to escape,
2706 * since they aren't really reasonable in a username anyway. Allowing
2707 * them would make it possible to inject any kind of custom filters in
2708 * the LDAP filter.
2709 */
2710 for (c = port->user_name; *c; c++)
2711 {
2712 if (*c == '*' ||
2713 *c == '(' ||
2714 *c == ')' ||
2715 *c == '\\' ||
2716 *c == '/')
2717 {
2718 ereport(LOG,
2719 (errmsg("invalid character in user name for LDAP authentication")));
2720 ldap_unbind(ldap);
2721 pfree(passwd);
2722 return STATUS_ERROR;
2723 }
2724 }
2725
2726 /*
2727 * Bind with a pre-defined username/password (if available) for
2728 * searching. If none is specified, this turns into an anonymous bind.
2729 */
2730 r = ldap_simple_bind_s(ldap,
2731 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2732 port->hba->ldapbindpasswd ? port->hba->ldapbindpasswd : "");
2733 if (r != LDAP_SUCCESS)
2734 {
2735 ereport(LOG,
2736 (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s",
2737 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2738 server_name,
2739 ldap_err2string(r)),
2740 errdetail_for_ldap(ldap)));
2741 ldap_unbind(ldap);
2742 pfree(passwd);
2743 return STATUS_ERROR;
2744 }
2745
2746 /* Build a custom filter or a single attribute filter? */
2747 if (port->hba->ldapsearchfilter)
2748 filter = FormatSearchFilter(port->hba->ldapsearchfilter, port->user_name);
2749 else if (port->hba->ldapsearchattribute)
2750 filter = psprintf("(%s=%s)", port->hba->ldapsearchattribute, port->user_name);
2751 else
2752 filter = psprintf("(uid=%s)", port->user_name);
2753
2754 r = ldap_search_s(ldap,
2755 port->hba->ldapbasedn,
2756 port->hba->ldapscope,
2757 filter,
2758 attributes,
2759 0,
2760 &search_message);
2761
2762 if (r != LDAP_SUCCESS)
2763 {
2764 ereport(LOG,
2765 (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",
2766 filter, server_name, ldap_err2string(r)),
2767 errdetail_for_ldap(ldap)));
2768 ldap_unbind(ldap);
2769 pfree(passwd);
2770 pfree(filter);
2771 return STATUS_ERROR;
2772 }
2773
2774 count = ldap_count_entries(ldap, search_message);
2775 if (count != 1)
2776 {
2777 if (count == 0)
2778 ereport(LOG,
2779 (errmsg("LDAP user \"%s\" does not exist", port->user_name),
2780 errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",
2781 filter, server_name)));
2782 else
2783 ereport(LOG,
2784 (errmsg("LDAP user \"%s\" is not unique", port->user_name),
2785 errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.",
2786 "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",
2787 count,
2788 filter, server_name, count)));
2789
2790 ldap_unbind(ldap);
2791 pfree(passwd);
2792 pfree(filter);
2793 ldap_msgfree(search_message);
2794 return STATUS_ERROR;
2795 }
2796
2797 entry = ldap_first_entry(ldap, search_message);
2798 dn = ldap_get_dn(ldap, entry);
2799 if (dn == NULL)
2800 {
2801 int error;
2802
2803 (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
2804 ereport(LOG,
2805 (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
2806 filter, server_name,
2807 ldap_err2string(error)),
2808 errdetail_for_ldap(ldap)));
2809 ldap_unbind(ldap);
2810 pfree(passwd);
2811 pfree(filter);
2812 ldap_msgfree(search_message);
2813 return STATUS_ERROR;
2814 }
2815 fulluser = pstrdup(dn);
2816
2817 pfree(filter);
2818 ldap_memfree(dn);
2819 ldap_msgfree(search_message);
2820
2821 /* Unbind and disconnect from the LDAP server */
2822 r = ldap_unbind_s(ldap);
2823 if (r != LDAP_SUCCESS)
2824 {
2825 ereport(LOG,
2826 (errmsg("could not unbind after searching for user \"%s\" on server \"%s\"",
2827 fulluser, server_name)));
2828 pfree(passwd);
2829 pfree(fulluser);
2830 return STATUS_ERROR;
2831 }
2832
2833 /*
2834 * Need to re-initialize the LDAP connection, so that we can bind to
2835 * it with a different username.
2836 */
2837 if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
2838 {
2839 pfree(passwd);
2840 pfree(fulluser);
2841
2842 /* Error message already sent */
2843 return STATUS_ERROR;
2844 }
2845 }
2846 else
2847 fulluser = psprintf("%s%s%s",
2848 port->hba->ldapprefix ? port->hba->ldapprefix : "",
2849 port->user_name,
2850 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
2851
2852 r = ldap_simple_bind_s(ldap, fulluser, passwd);
2853
2854 if (r != LDAP_SUCCESS)
2855 {
2856 ereport(LOG,
2857 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",
2858 fulluser, server_name, ldap_err2string(r)),
2859 errdetail_for_ldap(ldap)));
2860 ldap_unbind(ldap);
2861 pfree(passwd);
2862 pfree(fulluser);
2863 return STATUS_ERROR;
2864 }
2865
2866 /* Save the original bind DN as the authenticated identity. */
2867 set_authn_id(port, fulluser);
2868
2869 ldap_unbind(ldap);
2870 pfree(passwd);
2871 pfree(fulluser);
2872
2873 return STATUS_OK;
2874 }
2875
2876 /*
2877 * Add a detail error message text to the current error if one can be
2878 * constructed from the LDAP 'diagnostic message'.
2879 */
2880 static int
errdetail_for_ldap(LDAP * ldap)2881 errdetail_for_ldap(LDAP *ldap)
2882 {
2883 char *message;
2884 int rc;
2885
2886 rc = ldap_get_option(ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, &message);
2887 if (rc == LDAP_SUCCESS && message != NULL)
2888 {
2889 errdetail("LDAP diagnostics: %s", message);
2890 ldap_memfree(message);
2891 }
2892
2893 return 0;
2894 }
2895
2896 #endif /* USE_LDAP */
2897
2898
2899 /*----------------------------------------------------------------
2900 * SSL client certificate authentication
2901 *----------------------------------------------------------------
2902 */
2903 #ifdef USE_SSL
2904 static int
CheckCertAuth(Port * port)2905 CheckCertAuth(Port *port)
2906 {
2907 int status_check_usermap = STATUS_ERROR;
2908 char *peer_username = NULL;
2909
2910 Assert(port->ssl);
2911
2912 /* select the correct field to compare */
2913 switch (port->hba->clientcertname)
2914 {
2915 case clientCertDN:
2916 peer_username = port->peer_dn;
2917 break;
2918 case clientCertCN:
2919 peer_username = port->peer_cn;
2920 }
2921
2922 /* Make sure we have received a username in the certificate */
2923 if (peer_username == NULL ||
2924 strlen(peer_username) <= 0)
2925 {
2926 ereport(LOG,
2927 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
2928 port->user_name)));
2929 return STATUS_ERROR;
2930 }
2931
2932 if (port->hba->auth_method == uaCert)
2933 {
2934 /*
2935 * For cert auth, the client's Subject DN is always our authenticated
2936 * identity, even if we're only using its CN for authorization. Set
2937 * it now, rather than waiting for check_usermap() below, because
2938 * authentication has already succeeded and we want the log file to
2939 * reflect that.
2940 */
2941 if (!port->peer_dn)
2942 {
2943 /*
2944 * This should not happen as both peer_dn and peer_cn should be
2945 * set in this context.
2946 */
2947 ereport(LOG,
2948 (errmsg("certificate authentication failed for user \"%s\": unable to retrieve subject DN",
2949 port->user_name)));
2950 return STATUS_ERROR;
2951 }
2952
2953 set_authn_id(port, port->peer_dn);
2954 }
2955
2956 /* Just pass the certificate cn/dn to the usermap check */
2957 status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false);
2958 if (status_check_usermap != STATUS_OK)
2959 {
2960 /*
2961 * If clientcert=verify-full was specified and the authentication
2962 * method is other than uaCert, log the reason for rejecting the
2963 * authentication.
2964 */
2965 if (port->hba->clientcert == clientCertFull && port->hba->auth_method != uaCert)
2966 {
2967 switch (port->hba->clientcertname)
2968 {
2969 case clientCertDN:
2970 ereport(LOG,
2971 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",
2972 port->user_name)));
2973 break;
2974 case clientCertCN:
2975 ereport(LOG,
2976 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",
2977 port->user_name)));
2978 }
2979 }
2980 }
2981 return status_check_usermap;
2982 }
2983 #endif
2984
2985
2986 /*----------------------------------------------------------------
2987 * RADIUS authentication
2988 *----------------------------------------------------------------
2989 */
2990
2991 /*
2992 * RADIUS authentication is described in RFC2865 (and several others).
2993 */
2994
2995 #define RADIUS_VECTOR_LENGTH 16
2996 #define RADIUS_HEADER_LENGTH 20
2997 #define RADIUS_MAX_PASSWORD_LENGTH 128
2998
2999 /* Maximum size of a RADIUS packet we will create or accept */
3000 #define RADIUS_BUFFER_SIZE 1024
3001
3002 typedef struct
3003 {
3004 uint8 attribute;
3005 uint8 length;
3006 uint8 data[FLEXIBLE_ARRAY_MEMBER];
3007 } radius_attribute;
3008
3009 typedef struct
3010 {
3011 uint8 code;
3012 uint8 id;
3013 uint16 length;
3014 uint8 vector[RADIUS_VECTOR_LENGTH];
3015 /* this is a bit longer than strictly necessary: */
3016 char pad[RADIUS_BUFFER_SIZE - RADIUS_VECTOR_LENGTH];
3017 } radius_packet;
3018
3019 /* RADIUS packet types */
3020 #define RADIUS_ACCESS_REQUEST 1
3021 #define RADIUS_ACCESS_ACCEPT 2
3022 #define RADIUS_ACCESS_REJECT 3
3023
3024 /* RADIUS attributes */
3025 #define RADIUS_USER_NAME 1
3026 #define RADIUS_PASSWORD 2
3027 #define RADIUS_SERVICE_TYPE 6
3028 #define RADIUS_NAS_IDENTIFIER 32
3029
3030 /* RADIUS service types */
3031 #define RADIUS_AUTHENTICATE_ONLY 8
3032
3033 /* Seconds to wait - XXX: should be in a config variable! */
3034 #define RADIUS_TIMEOUT 3
3035
3036 static void
radius_add_attribute(radius_packet * packet,uint8 type,const unsigned char * data,int len)3037 radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
3038 {
3039 radius_attribute *attr;
3040
3041 if (packet->length + len > RADIUS_BUFFER_SIZE)
3042 {
3043 /*
3044 * With remotely realistic data, this can never happen. But catch it
3045 * just to make sure we don't overrun a buffer. We'll just skip adding
3046 * the broken attribute, which will in the end cause authentication to
3047 * fail.
3048 */
3049 elog(WARNING,
3050 "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
3051 type, len);
3052 return;
3053 }
3054
3055 attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
3056 attr->attribute = type;
3057 attr->length = len + 2; /* total size includes type and length */
3058 memcpy(attr->data, data, len);
3059 packet->length += attr->length;
3060 }
3061
3062 static int
CheckRADIUSAuth(Port * port)3063 CheckRADIUSAuth(Port *port)
3064 {
3065 char *passwd;
3066 ListCell *server,
3067 *secrets,
3068 *radiusports,
3069 *identifiers;
3070
3071 /* Make sure struct alignment is correct */
3072 Assert(offsetof(radius_packet, vector) == 4);
3073
3074 /* Verify parameters */
3075 if (list_length(port->hba->radiusservers) < 1)
3076 {
3077 ereport(LOG,
3078 (errmsg("RADIUS server not specified")));
3079 return STATUS_ERROR;
3080 }
3081
3082 if (list_length(port->hba->radiussecrets) < 1)
3083 {
3084 ereport(LOG,
3085 (errmsg("RADIUS secret not specified")));
3086 return STATUS_ERROR;
3087 }
3088
3089 /* Send regular password request to client, and get the response */
3090 sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
3091
3092 passwd = recv_password_packet(port);
3093 if (passwd == NULL)
3094 return STATUS_EOF; /* client wouldn't send password */
3095
3096 if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
3097 {
3098 ereport(LOG,
3099 (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
3100 pfree(passwd);
3101 return STATUS_ERROR;
3102 }
3103
3104 /*
3105 * Loop over and try each server in order.
3106 */
3107 secrets = list_head(port->hba->radiussecrets);
3108 radiusports = list_head(port->hba->radiusports);
3109 identifiers = list_head(port->hba->radiusidentifiers);
3110 foreach(server, port->hba->radiusservers)
3111 {
3112 int ret = PerformRadiusTransaction(lfirst(server),
3113 lfirst(secrets),
3114 radiusports ? lfirst(radiusports) : NULL,
3115 identifiers ? lfirst(identifiers) : NULL,
3116 port->user_name,
3117 passwd);
3118
3119 /*------
3120 * STATUS_OK = Login OK
3121 * STATUS_ERROR = Login not OK, but try next server
3122 * STATUS_EOF = Login not OK, and don't try next server
3123 *------
3124 */
3125 if (ret == STATUS_OK)
3126 {
3127 set_authn_id(port, port->user_name);
3128
3129 pfree(passwd);
3130 return STATUS_OK;
3131 }
3132 else if (ret == STATUS_EOF)
3133 {
3134 pfree(passwd);
3135 return STATUS_ERROR;
3136 }
3137
3138 /*
3139 * secret, port and identifiers either have length 0 (use default),
3140 * length 1 (use the same everywhere) or the same length as servers.
3141 * So if the length is >1, we advance one step. In other cases, we
3142 * don't and will then reuse the correct value.
3143 */
3144 if (list_length(port->hba->radiussecrets) > 1)
3145 secrets = lnext(port->hba->radiussecrets, secrets);
3146 if (list_length(port->hba->radiusports) > 1)
3147 radiusports = lnext(port->hba->radiusports, radiusports);
3148 if (list_length(port->hba->radiusidentifiers) > 1)
3149 identifiers = lnext(port->hba->radiusidentifiers, identifiers);
3150 }
3151
3152 /* No servers left to try, so give up */
3153 pfree(passwd);
3154 return STATUS_ERROR;
3155 }
3156
3157 static int
PerformRadiusTransaction(const char * server,const char * secret,const char * portstr,const char * identifier,const char * user_name,const char * passwd)3158 PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
3159 {
3160 radius_packet radius_send_pack;
3161 radius_packet radius_recv_pack;
3162 radius_packet *packet = &radius_send_pack;
3163 radius_packet *receivepacket = &radius_recv_pack;
3164 char *radius_buffer = (char *) &radius_send_pack;
3165 char *receive_buffer = (char *) &radius_recv_pack;
3166 int32 service = pg_hton32(RADIUS_AUTHENTICATE_ONLY);
3167 uint8 *cryptvector;
3168 int encryptedpasswordlen;
3169 uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
3170 uint8 *md5trailer;
3171 int packetlength;
3172 pgsocket sock;
3173
3174 #ifdef HAVE_IPV6
3175 struct sockaddr_in6 localaddr;
3176 struct sockaddr_in6 remoteaddr;
3177 #else
3178 struct sockaddr_in localaddr;
3179 struct sockaddr_in remoteaddr;
3180 #endif
3181 struct addrinfo hint;
3182 struct addrinfo *serveraddrs;
3183 int port;
3184 ACCEPT_TYPE_ARG3 addrsize;
3185 fd_set fdset;
3186 struct timeval endtime;
3187 int i,
3188 j,
3189 r;
3190
3191 /* Assign default values */
3192 if (portstr == NULL)
3193 portstr = "1812";
3194 if (identifier == NULL)
3195 identifier = "postgresql";
3196
3197 MemSet(&hint, 0, sizeof(hint));
3198 hint.ai_socktype = SOCK_DGRAM;
3199 hint.ai_family = AF_UNSPEC;
3200 port = atoi(portstr);
3201
3202 r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
3203 if (r || !serveraddrs)
3204 {
3205 ereport(LOG,
3206 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
3207 server, gai_strerror(r))));
3208 if (serveraddrs)
3209 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3210 return STATUS_ERROR;
3211 }
3212 /* XXX: add support for multiple returned addresses? */
3213
3214 /* Construct RADIUS packet */
3215 packet->code = RADIUS_ACCESS_REQUEST;
3216 packet->length = RADIUS_HEADER_LENGTH;
3217 if (!pg_strong_random(packet->vector, RADIUS_VECTOR_LENGTH))
3218 {
3219 ereport(LOG,
3220 (errmsg("could not generate random encryption vector")));
3221 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3222 return STATUS_ERROR;
3223 }
3224 packet->id = packet->vector[0];
3225 radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
3226 radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
3227 radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
3228
3229 /*
3230 * RADIUS password attributes are calculated as: e[0] = p[0] XOR
3231 * MD5(secret + Request Authenticator) for the first group of 16 octets,
3232 * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
3233 * (if necessary)
3234 */
3235 encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
3236 cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
3237 memcpy(cryptvector, secret, strlen(secret));
3238
3239 /* for the first iteration, we use the Request Authenticator vector */
3240 md5trailer = packet->vector;
3241 for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
3242 {
3243 memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
3244
3245 /*
3246 * .. and for subsequent iterations the result of the previous XOR
3247 * (calculated below)
3248 */
3249 md5trailer = encryptedpassword + i;
3250
3251 if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
3252 {
3253 ereport(LOG,
3254 (errmsg("could not perform MD5 encryption of password")));
3255 pfree(cryptvector);
3256 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3257 return STATUS_ERROR;
3258 }
3259
3260 for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
3261 {
3262 if (j < strlen(passwd))
3263 encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
3264 else
3265 encryptedpassword[j] = '\0' ^ encryptedpassword[j];
3266 }
3267 }
3268 pfree(cryptvector);
3269
3270 radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
3271
3272 /* Length needs to be in network order on the wire */
3273 packetlength = packet->length;
3274 packet->length = pg_hton16(packet->length);
3275
3276 sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
3277 if (sock == PGINVALID_SOCKET)
3278 {
3279 ereport(LOG,
3280 (errmsg("could not create RADIUS socket: %m")));
3281 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3282 return STATUS_ERROR;
3283 }
3284
3285 memset(&localaddr, 0, sizeof(localaddr));
3286 #ifdef HAVE_IPV6
3287 localaddr.sin6_family = serveraddrs[0].ai_family;
3288 localaddr.sin6_addr = in6addr_any;
3289 if (localaddr.sin6_family == AF_INET6)
3290 addrsize = sizeof(struct sockaddr_in6);
3291 else
3292 addrsize = sizeof(struct sockaddr_in);
3293 #else
3294 localaddr.sin_family = serveraddrs[0].ai_family;
3295 localaddr.sin_addr.s_addr = INADDR_ANY;
3296 addrsize = sizeof(struct sockaddr_in);
3297 #endif
3298
3299 if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
3300 {
3301 ereport(LOG,
3302 (errmsg("could not bind local RADIUS socket: %m")));
3303 closesocket(sock);
3304 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3305 return STATUS_ERROR;
3306 }
3307
3308 if (sendto(sock, radius_buffer, packetlength, 0,
3309 serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
3310 {
3311 ereport(LOG,
3312 (errmsg("could not send RADIUS packet: %m")));
3313 closesocket(sock);
3314 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3315 return STATUS_ERROR;
3316 }
3317
3318 /* Don't need the server address anymore */
3319 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3320
3321 /*
3322 * Figure out at what time we should time out. We can't just use a single
3323 * call to select() with a timeout, since somebody can be sending invalid
3324 * packets to our port thus causing us to retry in a loop and never time
3325 * out.
3326 *
3327 * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
3328 * the latch was set would improve the responsiveness to
3329 * timeouts/cancellations.
3330 */
3331 gettimeofday(&endtime, NULL);
3332 endtime.tv_sec += RADIUS_TIMEOUT;
3333
3334 while (true)
3335 {
3336 struct timeval timeout;
3337 struct timeval now;
3338 int64 timeoutval;
3339
3340 gettimeofday(&now, NULL);
3341 timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
3342 if (timeoutval <= 0)
3343 {
3344 ereport(LOG,
3345 (errmsg("timeout waiting for RADIUS response from %s",
3346 server)));
3347 closesocket(sock);
3348 return STATUS_ERROR;
3349 }
3350 timeout.tv_sec = timeoutval / 1000000;
3351 timeout.tv_usec = timeoutval % 1000000;
3352
3353 FD_ZERO(&fdset);
3354 FD_SET(sock, &fdset);
3355
3356 r = select(sock + 1, &fdset, NULL, NULL, &timeout);
3357 if (r < 0)
3358 {
3359 if (errno == EINTR)
3360 continue;
3361
3362 /* Anything else is an actual error */
3363 ereport(LOG,
3364 (errmsg("could not check status on RADIUS socket: %m")));
3365 closesocket(sock);
3366 return STATUS_ERROR;
3367 }
3368 if (r == 0)
3369 {
3370 ereport(LOG,
3371 (errmsg("timeout waiting for RADIUS response from %s",
3372 server)));
3373 closesocket(sock);
3374 return STATUS_ERROR;
3375 }
3376
3377 /*
3378 * Attempt to read the response packet, and verify the contents.
3379 *
3380 * Any packet that's not actually a RADIUS packet, or otherwise does
3381 * not validate as an explicit reject, is just ignored and we retry
3382 * for another packet (until we reach the timeout). This is to avoid
3383 * the possibility to denial-of-service the login by flooding the
3384 * server with invalid packets on the port that we're expecting the
3385 * RADIUS response on.
3386 */
3387
3388 addrsize = sizeof(remoteaddr);
3389 packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
3390 (struct sockaddr *) &remoteaddr, &addrsize);
3391 if (packetlength < 0)
3392 {
3393 ereport(LOG,
3394 (errmsg("could not read RADIUS response: %m")));
3395 closesocket(sock);
3396 return STATUS_ERROR;
3397 }
3398
3399 #ifdef HAVE_IPV6
3400 if (remoteaddr.sin6_port != pg_hton16(port))
3401 #else
3402 if (remoteaddr.sin_port != pg_hton16(port))
3403 #endif
3404 {
3405 #ifdef HAVE_IPV6
3406 ereport(LOG,
3407 (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3408 server, pg_ntoh16(remoteaddr.sin6_port))));
3409 #else
3410 ereport(LOG,
3411 (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3412 server, pg_ntoh16(remoteaddr.sin_port))));
3413 #endif
3414 continue;
3415 }
3416
3417 if (packetlength < RADIUS_HEADER_LENGTH)
3418 {
3419 ereport(LOG,
3420 (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
3421 continue;
3422 }
3423
3424 if (packetlength != pg_ntoh16(receivepacket->length))
3425 {
3426 ereport(LOG,
3427 (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
3428 server, pg_ntoh16(receivepacket->length), packetlength)));
3429 continue;
3430 }
3431
3432 if (packet->id != receivepacket->id)
3433 {
3434 ereport(LOG,
3435 (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
3436 server, receivepacket->id, packet->id)));
3437 continue;
3438 }
3439
3440 /*
3441 * Verify the response authenticator, which is calculated as
3442 * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
3443 */
3444 cryptvector = palloc(packetlength + strlen(secret));
3445
3446 memcpy(cryptvector, receivepacket, 4); /* code+id+length */
3447 memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
3448 * authenticator, from
3449 * original packet */
3450 if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
3451 * attributes at all */
3452 memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
3453 memcpy(cryptvector + packetlength, secret, strlen(secret));
3454
3455 if (!pg_md5_binary(cryptvector,
3456 packetlength + strlen(secret),
3457 encryptedpassword))
3458 {
3459 ereport(LOG,
3460 (errmsg("could not perform MD5 encryption of received packet")));
3461 pfree(cryptvector);
3462 continue;
3463 }
3464 pfree(cryptvector);
3465
3466 if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
3467 {
3468 ereport(LOG,
3469 (errmsg("RADIUS response from %s has incorrect MD5 signature",
3470 server)));
3471 continue;
3472 }
3473
3474 if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
3475 {
3476 closesocket(sock);
3477 return STATUS_OK;
3478 }
3479 else if (receivepacket->code == RADIUS_ACCESS_REJECT)
3480 {
3481 closesocket(sock);
3482 return STATUS_EOF;
3483 }
3484 else
3485 {
3486 ereport(LOG,
3487 (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
3488 server, receivepacket->code, user_name)));
3489 continue;
3490 }
3491 } /* while (true) */
3492 }
3493