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