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