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