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