]> granicus.if.org Git - postgresql/blob - src/backend/libpq/auth.c
Add support for using SSL client certificates to authenticate to the
[postgresql] / src / backend / libpq / auth.c
1 /*-------------------------------------------------------------------------
2  *
3  * auth.c
4  *        Routines to handle network authentication
5  *
6  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.173 2008/11/20 11:48:26 mha Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15
16 #include "postgres.h"
17
18 #include <sys/param.h>
19 #include <sys/socket.h>
20 #if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
21 #include <sys/uio.h>
22 #include <sys/ucred.h>
23 #endif
24 #ifdef HAVE_UCRED_H
25 # include <ucred.h>
26 #endif
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <unistd.h>
30
31 #include "libpq/auth.h"
32 #include "libpq/crypt.h"
33 #include "libpq/ip.h"
34 #include "libpq/libpq.h"
35 #include "libpq/pqformat.h"
36 #include "storage/ipc.h"
37
38 /*----------------------------------------------------------------
39  * Global authentication functions 
40  *----------------------------------------------------------------
41  */
42 static void sendAuthRequest(Port *port, AuthRequest areq);
43 static void auth_failed(Port *port, int status);
44 static char *recv_password_packet(Port *port);
45 static int      recv_and_check_password_packet(Port *port);
46
47
48 /*----------------------------------------------------------------
49  * Ident authentication
50  *----------------------------------------------------------------
51  */
52 /* Max size of username ident server can return */
53 #define IDENT_USERNAME_MAX 512
54
55 /* Standard TCP port number for Ident service.  Assigned by IANA */
56 #define IDENT_PORT 113
57
58 static int  authident(hbaPort *port);
59
60
61 /*----------------------------------------------------------------
62  * PAM authentication
63  *----------------------------------------------------------------
64  */
65 #ifdef USE_PAM
66 #ifdef HAVE_PAM_PAM_APPL_H
67 #include <pam/pam_appl.h>
68 #endif
69 #ifdef HAVE_SECURITY_PAM_APPL_H
70 #include <security/pam_appl.h>
71 #endif
72
73 #define PGSQL_PAM_SERVICE "postgresql"  /* Service name passed to PAM */
74
75 static int      CheckPAMAuth(Port *port, char *user, char *password);
76 static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
77                                          struct pam_response ** resp, void *appdata_ptr);
78
79 static struct pam_conv pam_passw_conv = {
80         &pam_passwd_conv_proc,
81         NULL
82 };
83
84 static char *pam_passwd = NULL; /* Workaround for Solaris 2.6 brokenness */
85 static Port *pam_port_cludge;   /* Workaround for passing "Port *port" into
86                                                                  * pam_passwd_conv_proc */
87 #endif   /* USE_PAM */
88
89
90 /*----------------------------------------------------------------
91  * LDAP authentication
92  *----------------------------------------------------------------
93  */
94 #ifdef USE_LDAP
95 #ifndef WIN32
96 /* We use a deprecated function to keep the codepath the same as win32. */
97 #define LDAP_DEPRECATED 1
98 #include <ldap.h>
99 #else
100 #include <winldap.h>
101
102 /* Correct header from the Platform SDK */
103 typedef
104 ULONG(*__ldap_start_tls_sA) (
105                                                          IN PLDAP ExternalHandle,
106                                                          OUT PULONG ServerReturnValue,
107                                                          OUT LDAPMessage ** result,
108                                                          IN PLDAPControlA * ServerControls,
109                                                          IN PLDAPControlA * ClientControls
110 );
111 #endif
112
113 static int      CheckLDAPAuth(Port *port);
114 #endif /* USE_LDAP */
115
116 /*----------------------------------------------------------------
117  * Cert authentication
118  *----------------------------------------------------------------
119  */
120 #ifdef USE_SSL
121 static int      CheckCertAuth(Port *port);
122 #endif
123
124
125 /*----------------------------------------------------------------
126  * Kerberos and GSSAPI GUCs
127  *----------------------------------------------------------------
128  */
129 char       *pg_krb_server_keyfile;
130 char       *pg_krb_srvnam;
131 bool            pg_krb_caseins_users;
132 char       *pg_krb_server_hostname = NULL;
133 char       *pg_krb_realm = NULL;
134
135
136 /*----------------------------------------------------------------
137  * MIT Kerberos authentication system - protocol version 5
138  *----------------------------------------------------------------
139  */
140 #ifdef KRB5
141 static int pg_krb5_recvauth(Port *port);
142
143 #include <krb5.h>
144 /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
145 #if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
146 #include <com_err.h>
147 #endif
148 /*
149  * Various krb5 state which is not connection specfic, and a flag to
150  * indicate whether we have initialised it yet.
151  */
152 static int      pg_krb5_initialised;
153 static krb5_context pg_krb5_context;
154 static krb5_keytab pg_krb5_keytab;
155 static krb5_principal pg_krb5_server;
156 #endif /* KRB5 */
157
158
159 /*----------------------------------------------------------------
160  * GSSAPI Authentication
161  *----------------------------------------------------------------
162  */
163 #ifdef ENABLE_GSS
164 #if defined(HAVE_GSSAPI_H)
165 #include <gssapi.h>
166 #else
167 #include <gssapi/gssapi.h>
168 #endif
169
170 static int pg_GSS_recvauth(Port *port);
171 #endif /* ENABLE_GSS */
172
173
174 /*----------------------------------------------------------------
175  * SSPI Authentication
176  *----------------------------------------------------------------
177  */
178 #ifdef ENABLE_SSPI
179 typedef         SECURITY_STATUS
180                         (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
181                                                                                                            PCtxtHandle, void **);
182 static int pg_SSPI_recvauth(Port *port);
183 #endif
184
185
186
187 /*----------------------------------------------------------------
188  * Global authentication functions
189  *----------------------------------------------------------------
190  */
191
192
193 /*
194  * Tell the user the authentication failed, but not (much about) why.
195  *
196  * There is a tradeoff here between security concerns and making life
197  * unnecessarily difficult for legitimate users.  We would not, for example,
198  * want to report the password we were expecting to receive...
199  * But it seems useful to report the username and authorization method
200  * in use, and these are items that must be presumed known to an attacker
201  * anyway.
202  * Note that many sorts of failure report additional information in the
203  * postmaster log, which we hope is only readable by good guys.
204  */
205 static void
206 auth_failed(Port *port, int status)
207 {
208         const char *errstr;
209
210         /*
211          * If we failed due to EOF from client, just quit; there's no point in
212          * trying to send a message to the client, and not much point in logging
213          * the failure in the postmaster log.  (Logging the failure might be
214          * desirable, were it not for the fact that libpq closes the connection
215          * unceremoniously if challenged for a password when it hasn't got one to
216          * send.  We'll get a useless log entry for every psql connection under
217          * password auth, even if it's perfectly successful, if we log STATUS_EOF
218          * events.)
219          */
220         if (status == STATUS_EOF)
221                 proc_exit(0);
222
223         switch (port->hba->auth_method)
224         {
225                 case uaReject:
226                         errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
227                         break;
228                 case uaKrb5:
229                         errstr = gettext_noop("Kerberos 5 authentication failed for user \"%s\"");
230                         break;
231                 case uaGSS:
232                         errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
233                         break;
234                 case uaSSPI:
235                         errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
236                         break;
237                 case uaTrust:
238                         errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
239                         break;
240                 case uaIdent:
241                         errstr = gettext_noop("Ident authentication failed for user \"%s\"");
242                         break;
243                 case uaMD5:
244                 case uaPassword:
245                         errstr = gettext_noop("password authentication failed for user \"%s\"");
246                         break;
247                 case uaPAM:
248                         errstr = gettext_noop("PAM authentication failed for user \"%s\"");
249                         break;
250                 case uaLDAP:
251                         errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
252                         break;
253                 default:
254                         errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
255                         break;
256         }
257
258         ereport(FATAL,
259                         (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
260                          errmsg(errstr, port->user_name)));
261         /* doesn't return */
262 }
263
264
265 /*
266  * Client authentication starts here.  If there is an error, this
267  * function does not return and the backend process is terminated.
268  */
269 void
270 ClientAuthentication(Port *port)
271 {
272         int                     status = STATUS_ERROR;
273
274         /*
275          * Get the authentication method to use for this frontend/database
276          * combination.  Note: a failure return indicates a problem with the hba
277          * config file, not with the request.  hba.c should have dropped an error
278          * message into the postmaster logfile if it failed.
279          */
280         if (hba_getauthmethod(port) != STATUS_OK)
281                 ereport(FATAL,
282                                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
283                                  errmsg("missing or erroneous pg_hba.conf file"),
284                                  errhint("See server log for details.")));
285
286         /*
287          * This is the first point where we have access to the hba record for
288          * the current connection, so perform any verifications based on the
289          * hba options field that should be done *before* the authentication
290          * here.
291          */
292         if (port->hba->clientcert)
293         {
294                 /*
295                  * When we parse pg_hba.conf, we have already made sure that we have
296                  * been able to load a certificate store. Thus, if a certificate is
297                  * present on the client, it has been verified against our root
298                  * certificate store, and the connection would have been aborted
299                  * already if it didn't verify ok.
300                  */
301 #ifdef USE_SSL
302                 if (!port->peer)
303                 {
304                         ereport(FATAL,
305                                         (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
306                                          errmsg("connection requires a valid client certificate")));
307                 }
308 #else
309                 /*
310                  * hba.c makes sure hba->clientcert can't be set unless OpenSSL
311                  * is present.
312                  */
313                 Assert(false);
314 #endif
315         }
316
317         /*
318          * Now proceed to do the actual authentication check
319          */
320         switch (port->hba->auth_method)
321         {
322                 case uaReject:
323
324                         /*
325                          * This could have come from an explicit "reject" entry in
326                          * pg_hba.conf, but more likely it means there was no matching
327                          * entry.  Take pity on the poor user and issue a helpful error
328                          * message.  NOTE: this is not a security breach, because all the
329                          * info reported here is known at the frontend and must be assumed
330                          * known to bad guys. We're merely helping out the less clueful
331                          * good guys.
332                          */
333                         {
334                                 char            hostinfo[NI_MAXHOST];
335
336                                 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
337                                                                    hostinfo, sizeof(hostinfo),
338                                                                    NULL, 0,
339                                                                    NI_NUMERICHOST);
340
341 #ifdef USE_SSL
342                                 ereport(FATAL,
343                                                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
344                                                  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
345                                                           hostinfo, port->user_name, port->database_name,
346                                                                 port->ssl ? _("SSL on") : _("SSL off"))));
347 #else
348                                 ereport(FATAL,
349                                                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
350                                                  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
351                                                    hostinfo, port->user_name, port->database_name)));
352 #endif
353                                 break;
354                         }
355
356                 case uaKrb5:
357 #ifdef KRB5
358                         sendAuthRequest(port, AUTH_REQ_KRB5);
359                         status = pg_krb5_recvauth(port);
360 #else
361                         Assert(false);
362 #endif
363                         break;
364
365                 case uaGSS:
366 #ifdef ENABLE_GSS
367                         sendAuthRequest(port, AUTH_REQ_GSS);
368                         status = pg_GSS_recvauth(port);
369 #else
370                         Assert(false);
371 #endif
372                         break;
373
374                 case uaSSPI:
375 #ifdef ENABLE_SSPI
376                         sendAuthRequest(port, AUTH_REQ_SSPI);
377                         status = pg_SSPI_recvauth(port);
378 #else
379                         Assert(false);
380 #endif
381                         break;
382
383                 case uaIdent:
384
385                         /*
386                          * If we are doing ident on unix-domain sockets, use SCM_CREDS
387                          * only if it is defined and SO_PEERCRED isn't.
388                          */
389 #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \
390         (defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
391          (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)))
392                         if (port->raddr.addr.ss_family == AF_UNIX)
393                         {
394 #if defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
395
396                                 /*
397                                  * Receive credentials on next message receipt, BSD/OS,
398                                  * NetBSD. We need to set this before the client sends the
399                                  * next packet.
400                                  */
401                                 int                     on = 1;
402
403                                 if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0)
404                                         ereport(FATAL,
405                                                         (errcode_for_socket_access(),
406                                            errmsg("could not enable credential reception: %m")));
407 #endif
408
409                                 sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
410                         }
411 #endif
412                         status = authident(port);
413                         break;
414
415                 case uaMD5:
416                         sendAuthRequest(port, AUTH_REQ_MD5);
417                         status = recv_and_check_password_packet(port);
418                         break;
419
420                 case uaPassword:
421                         sendAuthRequest(port, AUTH_REQ_PASSWORD);
422                         status = recv_and_check_password_packet(port);
423                         break;
424
425                 case uaPAM:
426 #ifdef USE_PAM
427                         pam_port_cludge = port;
428                         status = CheckPAMAuth(port, port->user_name, "");
429 #else
430                         Assert(false);
431 #endif   /* USE_PAM */
432                         break;
433
434                 case uaLDAP:
435 #ifdef USE_LDAP
436                         status = CheckLDAPAuth(port);
437 #else
438                         Assert(false);
439 #endif
440                         break;
441
442                 case uaCert:
443 #ifdef USE_SSL
444                         status = CheckCertAuth(port);
445 #else
446                         Assert(false);
447 #endif
448                         break;
449
450                 case uaTrust:
451                         status = STATUS_OK;
452                         break;
453         }
454
455         if (status == STATUS_OK)
456                 sendAuthRequest(port, AUTH_REQ_OK);
457         else
458                 auth_failed(port, status);
459 }
460
461
462 /*
463  * Send an authentication request packet to the frontend.
464  */
465 static void
466 sendAuthRequest(Port *port, AuthRequest areq)
467 {
468         StringInfoData buf;
469
470         pq_beginmessage(&buf, 'R');
471         pq_sendint(&buf, (int32) areq, sizeof(int32));
472
473         /* Add the salt for encrypted passwords. */
474         if (areq == AUTH_REQ_MD5)
475                 pq_sendbytes(&buf, port->md5Salt, 4);
476
477 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
478
479         /*
480          * Add the authentication data for the next step of the GSSAPI or SSPI
481          * negotiation.
482          */
483         else if (areq == AUTH_REQ_GSS_CONT)
484         {
485                 if (port->gss->outbuf.length > 0)
486                 {
487                         elog(DEBUG4, "sending GSS token of length %u",
488                                  (unsigned int) port->gss->outbuf.length);
489
490                         pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
491                 }
492         }
493 #endif
494
495         pq_endmessage(&buf);
496
497         /*
498          * Flush message so client will see it, except for AUTH_REQ_OK, which need
499          * not be sent until we are ready for queries.
500          */
501         if (areq != AUTH_REQ_OK)
502                 pq_flush();
503 }
504
505 /*
506  * Collect password response packet from frontend.
507  *
508  * Returns NULL if couldn't get password, else palloc'd string.
509  */
510 static char *
511 recv_password_packet(Port *port)
512 {
513         StringInfoData buf;
514
515         if (PG_PROTOCOL_MAJOR(port->proto) >= 3)
516         {
517                 /* Expect 'p' message type */
518                 int                     mtype;
519
520                 mtype = pq_getbyte();
521                 if (mtype != 'p')
522                 {
523                         /*
524                          * If the client just disconnects without offering a password,
525                          * don't make a log entry.  This is legal per protocol spec and in
526                          * fact commonly done by psql, so complaining just clutters the
527                          * log.
528                          */
529                         if (mtype != EOF)
530                                 ereport(COMMERROR,
531                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
532                                         errmsg("expected password response, got message type %d",
533                                                    mtype)));
534                         return NULL;            /* EOF or bad message type */
535                 }
536         }
537         else
538         {
539                 /* For pre-3.0 clients, avoid log entry if they just disconnect */
540                 if (pq_peekbyte() == EOF)
541                         return NULL;            /* EOF */
542         }
543
544         initStringInfo(&buf);
545         if (pq_getmessage(&buf, 1000))          /* receive password */
546         {
547                 /* EOF - pq_getmessage already logged a suitable message */
548                 pfree(buf.data);
549                 return NULL;
550         }
551
552         /*
553          * Apply sanity check: password packet length should agree with length of
554          * contained string.  Note it is safe to use strlen here because
555          * StringInfo is guaranteed to have an appended '\0'.
556          */
557         if (strlen(buf.data) + 1 != buf.len)
558                 ereport(COMMERROR,
559                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
560                                  errmsg("invalid password packet size")));
561
562         /* Do not echo password to logs, for security. */
563         ereport(DEBUG5,
564                         (errmsg("received password packet")));
565
566         /*
567          * Return the received string.  Note we do not attempt to do any
568          * character-set conversion on it; since we don't yet know the client's
569          * encoding, there wouldn't be much point.
570          */
571         return buf.data;
572 }
573
574
575 /*----------------------------------------------------------------
576  * MD5 and crypt authentication
577  *----------------------------------------------------------------
578  */
579
580 /*
581  * Called when we have sent an authorization request for a password.
582  * Get the response and check it.
583  */
584 static int
585 recv_and_check_password_packet(Port *port)
586 {
587         char       *passwd;
588         int                     result;
589
590         passwd = recv_password_packet(port);
591
592         if (passwd == NULL)
593                 return STATUS_EOF;              /* client wouldn't send password */
594
595         result = md5_crypt_verify(port, port->user_name, passwd);
596
597         pfree(passwd);
598
599         return result;
600 }
601
602
603 /*----------------------------------------------------------------
604  * MIT Kerberos authentication system - protocol version 5
605  *----------------------------------------------------------------
606  */
607 #ifdef KRB5
608
609 static int
610 pg_krb5_init(void)
611 {
612         krb5_error_code retval;
613         char       *khostname;
614
615         if (pg_krb5_initialised)
616                 return STATUS_OK;
617
618         retval = krb5_init_context(&pg_krb5_context);
619         if (retval)
620         {
621                 ereport(LOG,
622                                 (errmsg("Kerberos initialization returned error %d",
623                                                 retval)));
624                 com_err("postgres", retval, "while initializing krb5");
625                 return STATUS_ERROR;
626         }
627
628         retval = krb5_kt_resolve(pg_krb5_context, pg_krb_server_keyfile, &pg_krb5_keytab);
629         if (retval)
630         {
631                 ereport(LOG,
632                                 (errmsg("Kerberos keytab resolving returned error %d",
633                                                 retval)));
634                 com_err("postgres", retval, "while resolving keytab file \"%s\"",
635                                 pg_krb_server_keyfile);
636                 krb5_free_context(pg_krb5_context);
637                 return STATUS_ERROR;
638         }
639
640         /*
641          * If no hostname was specified, pg_krb_server_hostname is already NULL.
642          * If it's set to blank, force it to NULL.
643          */
644         khostname = pg_krb_server_hostname;
645         if (khostname && khostname[0] == '\0')
646                 khostname = NULL;
647
648         retval = krb5_sname_to_principal(pg_krb5_context,
649                                                                          khostname,
650                                                                          pg_krb_srvnam,
651                                                                          KRB5_NT_SRV_HST,
652                                                                          &pg_krb5_server);
653         if (retval)
654         {
655                 ereport(LOG,
656                                 (errmsg("Kerberos sname_to_principal(\"%s\", \"%s\") returned error %d",
657                  khostname ? khostname : "server hostname", pg_krb_srvnam, retval)));
658                 com_err("postgres", retval,
659                 "while getting server principal for server \"%s\" for service \"%s\"",
660                                 khostname ? khostname : "server hostname", pg_krb_srvnam);
661                 krb5_kt_close(pg_krb5_context, pg_krb5_keytab);
662                 krb5_free_context(pg_krb5_context);
663                 return STATUS_ERROR;
664         }
665
666         pg_krb5_initialised = 1;
667         return STATUS_OK;
668 }
669
670
671 /*
672  * pg_krb5_recvauth -- server routine to receive authentication information
673  *                                         from the client
674  *
675  * We still need to compare the username obtained from the client's setup
676  * packet to the authenticated name.
677  *
678  * We have our own keytab file because postgres is unlikely to run as root,
679  * and so cannot read the default keytab.
680  */
681 static int
682 pg_krb5_recvauth(Port *port)
683 {
684         krb5_error_code retval;
685         int                     ret;
686         krb5_auth_context auth_context = NULL;
687         krb5_ticket *ticket;
688         char       *kusername;
689         char       *cp;
690
691         if (get_role_line(port->user_name) == NULL)
692                 return STATUS_ERROR;
693
694         ret = pg_krb5_init();
695         if (ret != STATUS_OK)
696                 return ret;
697
698         retval = krb5_recvauth(pg_krb5_context, &auth_context,
699                                                    (krb5_pointer) & port->sock, pg_krb_srvnam,
700                                                    pg_krb5_server, 0, pg_krb5_keytab, &ticket);
701         if (retval)
702         {
703                 ereport(LOG,
704                                 (errmsg("Kerberos recvauth returned error %d",
705                                                 retval)));
706                 com_err("postgres", retval, "from krb5_recvauth");
707                 return STATUS_ERROR;
708         }
709
710         /*
711          * The "client" structure comes out of the ticket and is therefore
712          * authenticated.  Use it to check the username obtained from the
713          * postmaster startup packet.
714          */
715 #if defined(HAVE_KRB5_TICKET_ENC_PART2)
716         retval = krb5_unparse_name(pg_krb5_context,
717                                                            ticket->enc_part2->client, &kusername);
718 #elif defined(HAVE_KRB5_TICKET_CLIENT)
719         retval = krb5_unparse_name(pg_krb5_context,
720                                                            ticket->client, &kusername);
721 #else
722 #error "bogus configuration"
723 #endif
724         if (retval)
725         {
726                 ereport(LOG,
727                                 (errmsg("Kerberos unparse_name returned error %d",
728                                                 retval)));
729                 com_err("postgres", retval, "while unparsing client name");
730                 krb5_free_ticket(pg_krb5_context, ticket);
731                 krb5_auth_con_free(pg_krb5_context, auth_context);
732                 return STATUS_ERROR;
733         }
734
735         cp = strchr(kusername, '@');
736         if (cp)
737         {
738                 *cp = '\0';
739                 cp++;
740
741                 if (pg_krb_realm != NULL && strlen(pg_krb_realm))
742                 {
743                         /* Match realm against configured */
744                         if (pg_krb_caseins_users)
745                                 ret = pg_strcasecmp(pg_krb_realm, cp);
746                         else
747                                 ret = strcmp(pg_krb_realm, cp);
748
749                         if (ret)
750                         {
751                                 elog(DEBUG2,
752                                          "krb5 realm (%s) and configured realm (%s) don't match",
753                                          cp, pg_krb_realm);
754
755                                 krb5_free_ticket(pg_krb5_context, ticket);
756                                 krb5_auth_con_free(pg_krb5_context, auth_context);
757                                 return STATUS_ERROR;
758                         }
759                 }
760         }
761         else if (pg_krb_realm && strlen(pg_krb_realm))
762         {
763                 elog(DEBUG2,
764                          "krb5 did not return realm but realm matching was requested");
765
766                 krb5_free_ticket(pg_krb5_context, ticket);
767                 krb5_auth_con_free(pg_krb5_context, auth_context);
768                 return STATUS_ERROR;
769         }
770
771         ret = check_usermap(port->hba->usermap, port->user_name, kusername,
772                                                 pg_krb_caseins_users);
773
774         krb5_free_ticket(pg_krb5_context, ticket);
775         krb5_auth_con_free(pg_krb5_context, auth_context);
776         free(kusername);
777
778         return ret;
779 }
780 #endif   /* KRB5 */
781
782
783 /*----------------------------------------------------------------
784  * GSSAPI authentication system
785  *----------------------------------------------------------------
786  */
787 #ifdef ENABLE_GSS
788
789 #if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
790 /*
791  * MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
792  * that contain the OIDs required. Redefine here, values copied
793  * from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
794  */
795 static const gss_OID_desc GSS_C_NT_USER_NAME_desc =
796 {10, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"};
797 static GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_desc;
798 #endif
799
800
801 static void
802 pg_GSS_error(int severity, char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
803 {
804         gss_buffer_desc gmsg;
805         OM_uint32       lmaj_s,
806                                 lmin_s,
807                                 msg_ctx;
808         char            msg_major[128],
809                                 msg_minor[128];
810
811         /* Fetch major status message */
812         msg_ctx = 0;
813         lmaj_s = gss_display_status(&lmin_s, maj_stat, GSS_C_GSS_CODE,
814                                                                 GSS_C_NO_OID, &msg_ctx, &gmsg);
815         strlcpy(msg_major, gmsg.value, sizeof(msg_major));
816         gss_release_buffer(&lmin_s, &gmsg);
817
818         if (msg_ctx)
819
820                 /*
821                  * More than one message available. XXX: Should we loop and read all
822                  * messages? (same below)
823                  */
824                 ereport(WARNING,
825                                 (errmsg_internal("incomplete GSS error report")));
826
827         /* Fetch mechanism minor status message */
828         msg_ctx = 0;
829         lmaj_s = gss_display_status(&lmin_s, min_stat, GSS_C_MECH_CODE,
830                                                                 GSS_C_NO_OID, &msg_ctx, &gmsg);
831         strlcpy(msg_minor, gmsg.value, sizeof(msg_minor));
832         gss_release_buffer(&lmin_s, &gmsg);
833
834         if (msg_ctx)
835                 ereport(WARNING,
836                                 (errmsg_internal("incomplete GSS minor error report")));
837
838         /*
839          * errmsg_internal, since translation of the first part must be done
840          * before calling this function anyway.
841          */
842         ereport(severity,
843                         (errmsg_internal("%s", errmsg),
844                          errdetail("%s: %s", msg_major, msg_minor)));
845 }
846
847 static int
848 pg_GSS_recvauth(Port *port)
849 {
850         OM_uint32       maj_stat,
851                                 min_stat,
852                                 lmin_s,
853                                 gflags;
854         int                     mtype;
855         int                     ret;
856         StringInfoData buf;
857         gss_buffer_desc gbuf;
858
859         /*
860          * GSS auth is not supported for protocol versions before 3, because it
861          * relies on the overall message length word to determine the GSS payload
862          * size in AuthenticationGSSContinue and PasswordMessage messages.
863          * (This is, in fact, a design error in our GSS support, because protocol
864          * messages are supposed to be parsable without relying on the length
865          * word; but it's not worth changing it now.)
866          */
867         if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
868                 ereport(FATAL,
869                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
870                                  errmsg("GSSAPI is not supported in protocol version 2")));
871
872         if (pg_krb_server_keyfile && strlen(pg_krb_server_keyfile) > 0)
873         {
874                 /*
875                  * Set default Kerberos keytab file for the Krb5 mechanism.
876                  *
877                  * setenv("KRB5_KTNAME", pg_krb_server_keyfile, 0); except setenv()
878                  * not always available.
879                  */
880                 if (getenv("KRB5_KTNAME") == NULL)
881                 {
882                         size_t  kt_len = strlen(pg_krb_server_keyfile) + 14;
883                         char   *kt_path = malloc(kt_len);
884
885                         if (!kt_path)
886                         {
887                                 ereport(LOG,
888                                                 (errcode(ERRCODE_OUT_OF_MEMORY),
889                                                  errmsg("out of memory")));
890                                 return STATUS_ERROR;
891                         }
892                         snprintf(kt_path, kt_len, "KRB5_KTNAME=%s", pg_krb_server_keyfile);
893                         putenv(kt_path);
894                 }
895         }
896
897         /*
898          * We accept any service principal that's present in our keytab. This
899          * increases interoperability between kerberos implementations that see
900          * for example case sensitivity differently, while not really opening up
901          * any vector of attack.
902          */
903         port->gss->cred = GSS_C_NO_CREDENTIAL;
904
905         /*
906          * Initialize sequence with an empty context
907          */
908         port->gss->ctx = GSS_C_NO_CONTEXT;
909
910         /*
911          * Loop through GSSAPI message exchange. This exchange can consist of
912          * multiple messags sent in both directions. First message is always from
913          * the client. All messages from client to server are password packets
914          * (type 'p').
915          */
916         do
917         {
918                 mtype = pq_getbyte();
919                 if (mtype != 'p')
920                 {
921                         /* Only log error if client didn't disconnect. */
922                         if (mtype != EOF)
923                                 ereport(COMMERROR,
924                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
925                                                  errmsg("expected GSS response, got message type %d",
926                                                                 mtype)));
927                         return STATUS_ERROR;
928                 }
929
930                 /* Get the actual GSS token */
931                 initStringInfo(&buf);
932                 if (pq_getmessage(&buf, 2000))
933                 {
934                         /* EOF - pq_getmessage already logged error */
935                         pfree(buf.data);
936                         return STATUS_ERROR;
937                 }
938
939                 /* Map to GSSAPI style buffer */
940                 gbuf.length = buf.len;
941                 gbuf.value = buf.data;
942
943                 elog(DEBUG4, "Processing received GSS token of length %u",
944                          (unsigned int) gbuf.length);
945
946                 maj_stat = gss_accept_sec_context(
947                                                                                   &min_stat,
948                                                                                   &port->gss->ctx,
949                                                                                   port->gss->cred,
950                                                                                   &gbuf,
951                                                                                   GSS_C_NO_CHANNEL_BINDINGS,
952                                                                                   &port->gss->name,
953                                                                                   NULL,
954                                                                                   &port->gss->outbuf,
955                                                                                   &gflags,
956                                                                                   NULL,
957                                                                                   NULL);
958
959                 /* gbuf no longer used */
960                 pfree(buf.data);
961
962                 elog(DEBUG5, "gss_accept_sec_context major: %d, "
963                          "minor: %d, outlen: %u, outflags: %x",
964                          maj_stat, min_stat,
965                          (unsigned int) port->gss->outbuf.length, gflags);
966
967                 if (port->gss->outbuf.length != 0)
968                 {
969                         /*
970                          * Negotiation generated data to be sent to the client.
971                          */
972                         OM_uint32       lmin_s;
973
974                         elog(DEBUG4, "sending GSS response token of length %u",
975                                  (unsigned int) port->gss->outbuf.length);
976
977                         sendAuthRequest(port, AUTH_REQ_GSS_CONT);
978
979                         gss_release_buffer(&lmin_s, &port->gss->outbuf);
980                 }
981
982                 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
983                 {
984                         OM_uint32       lmin_s;
985
986                         gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
987                         pg_GSS_error(ERROR,
988                                            gettext_noop("accepting GSS security context failed"),
989                                                  maj_stat, min_stat);
990                 }
991
992                 if (maj_stat == GSS_S_CONTINUE_NEEDED)
993                         elog(DEBUG4, "GSS continue needed");
994
995         } while (maj_stat == GSS_S_CONTINUE_NEEDED);
996
997         if (port->gss->cred != GSS_C_NO_CREDENTIAL)
998         {
999                 /*
1000                  * Release service principal credentials
1001                  */
1002                 gss_release_cred(&min_stat, &port->gss->cred);
1003         }
1004
1005         /*
1006          * GSS_S_COMPLETE indicates that authentication is now complete.
1007          *
1008          * Get the name of the user that authenticated, and compare it to the pg
1009          * username that was specified for the connection.
1010          */
1011         maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
1012         if (maj_stat != GSS_S_COMPLETE)
1013                 pg_GSS_error(ERROR,
1014                                          gettext_noop("retrieving GSS user name failed"),
1015                                          maj_stat, min_stat);
1016
1017         /*
1018          * Split the username at the realm separator
1019          */
1020         if (strchr(gbuf.value, '@'))
1021         {
1022                 char       *cp = strchr(gbuf.value, '@');
1023
1024                 *cp = '\0';
1025                 cp++;
1026
1027                 if (pg_krb_realm != NULL && strlen(pg_krb_realm))
1028                 {
1029                         /*
1030                          * Match the realm part of the name first
1031                          */
1032                         if (pg_krb_caseins_users)
1033                                 ret = pg_strcasecmp(pg_krb_realm, cp);
1034                         else
1035                                 ret = strcmp(pg_krb_realm, cp);
1036
1037                         if (ret)
1038                         {
1039                                 /* GSS realm does not match */
1040                                 elog(DEBUG2,
1041                                    "GSSAPI realm (%s) and configured realm (%s) don't match",
1042                                          cp, pg_krb_realm);
1043                                 gss_release_buffer(&lmin_s, &gbuf);
1044                                 return STATUS_ERROR;
1045                         }
1046                 }
1047         }
1048         else if (pg_krb_realm && strlen(pg_krb_realm))
1049         {
1050                 elog(DEBUG2,
1051                          "GSSAPI did not return realm but realm matching was requested");
1052
1053                 gss_release_buffer(&lmin_s, &gbuf);
1054                 return STATUS_ERROR;
1055         }
1056
1057         ret = check_usermap(port->hba->usermap, port->user_name, gbuf.value,
1058                                                 pg_krb_caseins_users);
1059
1060         gss_release_buffer(&lmin_s, &gbuf);
1061
1062         return STATUS_OK;
1063 }
1064 #endif   /* ENABLE_GSS */
1065
1066
1067 /*----------------------------------------------------------------
1068  * SSPI authentication system
1069  *----------------------------------------------------------------
1070  */
1071 #ifdef ENABLE_SSPI
1072 static void
1073 pg_SSPI_error(int severity, char *errmsg, SECURITY_STATUS r)
1074 {
1075         char            sysmsg[256];
1076
1077         if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, r, 0, sysmsg, sizeof(sysmsg), NULL) == 0)
1078                 ereport(severity,
1079                                 (errmsg_internal("%s", errmsg),
1080                                  errdetail("SSPI error %x", (unsigned int) r)));
1081         else
1082                 ereport(severity,
1083                                 (errmsg_internal("%s", errmsg),
1084                                  errdetail("%s (%x)", sysmsg, (unsigned int) r)));
1085 }
1086
1087 static int
1088 pg_SSPI_recvauth(Port *port)
1089 {
1090         int                     mtype;
1091         StringInfoData buf;
1092         SECURITY_STATUS r;
1093         CredHandle      sspicred;
1094         CtxtHandle *sspictx = NULL,
1095                                 newctx;
1096         TimeStamp       expiry;
1097         ULONG           contextattr;
1098         SecBufferDesc inbuf;
1099         SecBufferDesc outbuf;
1100         SecBuffer       OutBuffers[1];
1101         SecBuffer       InBuffers[1];
1102         HANDLE          token;
1103         TOKEN_USER *tokenuser;
1104         DWORD           retlen;
1105         char            accountname[MAXPGPATH];
1106         char            domainname[MAXPGPATH];
1107         DWORD           accountnamesize = sizeof(accountname);
1108         DWORD           domainnamesize = sizeof(domainname);
1109         SID_NAME_USE accountnameuse;
1110         HMODULE         secur32;
1111         QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken;
1112
1113         /*
1114          * SSPI auth is not supported for protocol versions before 3, because it
1115          * relies on the overall message length word to determine the SSPI payload
1116          * size in AuthenticationGSSContinue and PasswordMessage messages.
1117          * (This is, in fact, a design error in our SSPI support, because protocol
1118          * messages are supposed to be parsable without relying on the length
1119          * word; but it's not worth changing it now.)
1120          */
1121         if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
1122                 ereport(FATAL,
1123                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1124                                  errmsg("SSPI is not supported in protocol version 2")));
1125
1126         /*
1127          * Acquire a handle to the server credentials.
1128          */
1129         r = AcquireCredentialsHandle(NULL,
1130                                                                  "negotiate",
1131                                                                  SECPKG_CRED_INBOUND,
1132                                                                  NULL,
1133                                                                  NULL,
1134                                                                  NULL,
1135                                                                  NULL,
1136                                                                  &sspicred,
1137                                                                  &expiry);
1138         if (r != SEC_E_OK)
1139                 pg_SSPI_error(ERROR,
1140                            gettext_noop("could not acquire SSPI credentials handle"), r);
1141
1142         /*
1143          * Loop through SSPI message exchange. This exchange can consist of
1144          * multiple messags sent in both directions. First message is always from
1145          * the client. All messages from client to server are password packets
1146          * (type 'p').
1147          */
1148         do
1149         {
1150                 mtype = pq_getbyte();
1151                 if (mtype != 'p')
1152                 {
1153                         /* Only log error if client didn't disconnect. */
1154                         if (mtype != EOF)
1155                                 ereport(COMMERROR,
1156                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1157                                                  errmsg("expected SSPI response, got message type %d",
1158                                                                 mtype)));
1159                         return STATUS_ERROR;
1160                 }
1161
1162                 /* Get the actual SSPI token */
1163                 initStringInfo(&buf);
1164                 if (pq_getmessage(&buf, 2000))
1165                 {
1166                         /* EOF - pq_getmessage already logged error */
1167                         pfree(buf.data);
1168                         return STATUS_ERROR;
1169                 }
1170
1171                 /* Map to SSPI style buffer */
1172                 inbuf.ulVersion = SECBUFFER_VERSION;
1173                 inbuf.cBuffers = 1;
1174                 inbuf.pBuffers = InBuffers;
1175                 InBuffers[0].pvBuffer = buf.data;
1176                 InBuffers[0].cbBuffer = buf.len;
1177                 InBuffers[0].BufferType = SECBUFFER_TOKEN;
1178
1179                 /* Prepare output buffer */
1180                 OutBuffers[0].pvBuffer = NULL;
1181                 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
1182                 OutBuffers[0].cbBuffer = 0;
1183                 outbuf.cBuffers = 1;
1184                 outbuf.pBuffers = OutBuffers;
1185                 outbuf.ulVersion = SECBUFFER_VERSION;
1186
1187
1188                 elog(DEBUG4, "Processing received SSPI token of length %u",
1189                          (unsigned int) buf.len);
1190
1191                 r = AcceptSecurityContext(&sspicred,
1192                                                                   sspictx,
1193                                                                   &inbuf,
1194                                                                   ASC_REQ_ALLOCATE_MEMORY,
1195                                                                   SECURITY_NETWORK_DREP,
1196                                                                   &newctx,
1197                                                                   &outbuf,
1198                                                                   &contextattr,
1199                                                                   NULL);
1200
1201                 /* input buffer no longer used */
1202                 pfree(buf.data);
1203
1204                 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
1205                 {
1206                         /*
1207                          * Negotiation generated data to be sent to the client.
1208                          */
1209                         elog(DEBUG4, "sending SSPI response token of length %u",
1210                                  (unsigned int) outbuf.pBuffers[0].cbBuffer);
1211
1212                         port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
1213                         port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
1214
1215                         sendAuthRequest(port, AUTH_REQ_GSS_CONT);
1216
1217                         FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
1218                 }
1219
1220                 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
1221                 {
1222                         if (sspictx != NULL)
1223                         {
1224                                 DeleteSecurityContext(sspictx);
1225                                 free(sspictx);
1226                         }
1227                         FreeCredentialsHandle(&sspicred);
1228                         pg_SSPI_error(ERROR,
1229                                   gettext_noop("could not accept SSPI security context"), r);
1230                 }
1231
1232                 if (sspictx == NULL)
1233                 {
1234                         sspictx = malloc(sizeof(CtxtHandle));
1235                         if (sspictx == NULL)
1236                                 ereport(ERROR,
1237                                                 (errmsg("out of memory")));
1238
1239                         memcpy(sspictx, &newctx, sizeof(CtxtHandle));
1240                 }
1241
1242                 if (r == SEC_I_CONTINUE_NEEDED)
1243                         elog(DEBUG4, "SSPI continue needed");
1244
1245         } while (r == SEC_I_CONTINUE_NEEDED);
1246
1247
1248         /*
1249          * Release service principal credentials
1250          */
1251         FreeCredentialsHandle(&sspicred);
1252
1253
1254         /*
1255          * SEC_E_OK indicates that authentication is now complete.
1256          *
1257          * Get the name of the user that authenticated, and compare it to the pg
1258          * username that was specified for the connection.
1259          *
1260          * MingW is missing the export for QuerySecurityContextToken in the
1261          * secur32 library, so we have to load it dynamically.
1262          */
1263
1264         secur32 = LoadLibrary("SECUR32.DLL");
1265         if (secur32 == NULL)
1266                 ereport(ERROR,
1267                                 (errmsg_internal("could not load secur32.dll: %d",
1268                                                                  (int) GetLastError())));
1269
1270         _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN)
1271                 GetProcAddress(secur32, "QuerySecurityContextToken");
1272         if (_QuerySecurityContextToken == NULL)
1273         {
1274                 FreeLibrary(secur32);
1275                 ereport(ERROR,
1276                                 (errmsg_internal("could not locate QuerySecurityContextToken in secur32.dll: %d",
1277                                                                  (int) GetLastError())));
1278         }
1279
1280         r = (_QuerySecurityContextToken) (sspictx, &token);
1281         if (r != SEC_E_OK)
1282         {
1283                 FreeLibrary(secur32);
1284                 pg_SSPI_error(ERROR,
1285                            gettext_noop("could not get security token from context"), r);
1286         }
1287
1288         FreeLibrary(secur32);
1289
1290         /*
1291          * No longer need the security context, everything from here on uses the
1292          * token instead.
1293          */
1294         DeleteSecurityContext(sspictx);
1295         free(sspictx);
1296
1297         if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
1298                 ereport(ERROR,
1299                          (errmsg_internal("could not get token user size: error code %d",
1300                                                           (int) GetLastError())));
1301
1302         tokenuser = malloc(retlen);
1303         if (tokenuser == NULL)
1304                 ereport(ERROR,
1305                                 (errmsg("out of memory")));
1306
1307         if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
1308                 ereport(ERROR,
1309                                 (errmsg_internal("could not get user token: error code %d",
1310                                                                  (int) GetLastError())));
1311
1312         if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
1313                                                   domainname, &domainnamesize, &accountnameuse))
1314                 ereport(ERROR,
1315                           (errmsg_internal("could not lookup acconut sid: error code %d",
1316                                                            (int) GetLastError())));
1317
1318         free(tokenuser);
1319
1320         /*
1321          * Compare realm/domain if requested. In SSPI, always compare case
1322          * insensitive.
1323          */
1324         if (pg_krb_realm && strlen(pg_krb_realm))
1325         {
1326                 if (pg_strcasecmp(pg_krb_realm, domainname))
1327                 {
1328                         elog(DEBUG2,
1329                                  "SSPI domain (%s) and configured domain (%s) don't match",
1330                                  domainname, pg_krb_realm);
1331
1332                         return STATUS_ERROR;
1333                 }
1334         }
1335
1336         /*
1337          * We have the username (without domain/realm) in accountname, compare to
1338          * the supplied value. In SSPI, always compare case insensitive.
1339          */
1340         return check_usermap(port->hba->usermap, port->user_name, accountname, true);
1341 }
1342 #endif   /* ENABLE_SSPI */
1343
1344
1345
1346 /*----------------------------------------------------------------
1347  * Ident authentication system
1348  *----------------------------------------------------------------
1349  */
1350
1351 /*
1352  *      Parse the string "*ident_response" as a response from a query to an Ident
1353  *      server.  If it's a normal response indicating a user name, return true
1354  *      and store the user name at *ident_user. If it's anything else,
1355  *      return false.
1356  */
1357 static bool
1358 interpret_ident_response(const char *ident_response,
1359                                                  char *ident_user)
1360 {
1361         const char *cursor = ident_response;            /* Cursor into *ident_response */
1362
1363         /*
1364          * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1365          */
1366         if (strlen(ident_response) < 2)
1367                 return false;
1368         else if (ident_response[strlen(ident_response) - 2] != '\r')
1369                 return false;
1370         else
1371         {
1372                 while (*cursor != ':' && *cursor != '\r')
1373                         cursor++;                       /* skip port field */
1374
1375                 if (*cursor != ':')
1376                         return false;
1377                 else
1378                 {
1379                         /* We're positioned to colon before response type field */
1380                         char            response_type[80];
1381                         int                     i;              /* Index into *response_type */
1382
1383                         cursor++;                       /* Go over colon */
1384                         while (pg_isblank(*cursor))
1385                                 cursor++;               /* skip blanks */
1386                         i = 0;
1387                         while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1388                                    i < (int) (sizeof(response_type) - 1))
1389                                 response_type[i++] = *cursor++;
1390                         response_type[i] = '\0';
1391                         while (pg_isblank(*cursor))
1392                                 cursor++;               /* skip blanks */
1393                         if (strcmp(response_type, "USERID") != 0)
1394                                 return false;
1395                         else
1396                         {
1397                                 /*
1398                                  * It's a USERID response.  Good.  "cursor" should be pointing
1399                                  * to the colon that precedes the operating system type.
1400                                  */
1401                                 if (*cursor != ':')
1402                                         return false;
1403                                 else
1404                                 {
1405                                         cursor++;       /* Go over colon */
1406                                         /* Skip over operating system field. */
1407                                         while (*cursor != ':' && *cursor != '\r')
1408                                                 cursor++;
1409                                         if (*cursor != ':')
1410                                                 return false;
1411                                         else
1412                                         {
1413                                                 int                     i;      /* Index into *ident_user */
1414
1415                                                 cursor++;               /* Go over colon */
1416                                                 while (pg_isblank(*cursor))
1417                                                         cursor++;       /* skip blanks */
1418                                                 /* Rest of line is user name.  Copy it over. */
1419                                                 i = 0;
1420                                                 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1421                                                         ident_user[i++] = *cursor++;
1422                                                 ident_user[i] = '\0';
1423                                                 return true;
1424                                         }
1425                                 }
1426                         }
1427                 }
1428         }
1429 }
1430
1431
1432 /*
1433  *      Talk to the ident server on host "remote_ip_addr" and find out who
1434  *      owns the tcp connection from his port "remote_port" to port
1435  *      "local_port_addr" on host "local_ip_addr".      Return the user name the
1436  *      ident server gives as "*ident_user".
1437  *
1438  *      IP addresses and port numbers are in network byte order.
1439  *
1440  *      But iff we're unable to get the information from ident, return false.
1441  */
1442 static bool
1443 ident_inet(const SockAddr remote_addr,
1444                    const SockAddr local_addr,
1445                    char *ident_user)
1446 {
1447         int                     sock_fd,                /* File descriptor for socket on which we talk
1448                                                                  * to Ident */
1449                                 rc;                             /* Return code from a locally called function */
1450         bool            ident_return;
1451         char            remote_addr_s[NI_MAXHOST];
1452         char            remote_port[NI_MAXSERV];
1453         char            local_addr_s[NI_MAXHOST];
1454         char            local_port[NI_MAXSERV];
1455         char            ident_port[NI_MAXSERV];
1456         char            ident_query[80];
1457         char            ident_response[80 + IDENT_USERNAME_MAX];
1458         struct addrinfo *ident_serv = NULL,
1459                            *la = NULL,
1460                                 hints;
1461
1462         /*
1463          * Might look a little weird to first convert it to text and then back to
1464          * sockaddr, but it's protocol independent.
1465          */
1466         pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1467                                            remote_addr_s, sizeof(remote_addr_s),
1468                                            remote_port, sizeof(remote_port),
1469                                            NI_NUMERICHOST | NI_NUMERICSERV);
1470         pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1471                                            local_addr_s, sizeof(local_addr_s),
1472                                            local_port, sizeof(local_port),
1473                                            NI_NUMERICHOST | NI_NUMERICSERV);
1474
1475         snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1476         hints.ai_flags = AI_NUMERICHOST;
1477         hints.ai_family = remote_addr.addr.ss_family;
1478         hints.ai_socktype = SOCK_STREAM;
1479         hints.ai_protocol = 0;
1480         hints.ai_addrlen = 0;
1481         hints.ai_canonname = NULL;
1482         hints.ai_addr = NULL;
1483         hints.ai_next = NULL;
1484         rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1485         if (rc || !ident_serv)
1486         {
1487                 if (ident_serv)
1488                         pg_freeaddrinfo_all(hints.ai_family, ident_serv);
1489                 return false;                   /* we don't expect this to happen */
1490         }
1491
1492         hints.ai_flags = AI_NUMERICHOST;
1493         hints.ai_family = local_addr.addr.ss_family;
1494         hints.ai_socktype = SOCK_STREAM;
1495         hints.ai_protocol = 0;
1496         hints.ai_addrlen = 0;
1497         hints.ai_canonname = NULL;
1498         hints.ai_addr = NULL;
1499         hints.ai_next = NULL;
1500         rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1501         if (rc || !la)
1502         {
1503                 if (la)
1504                         pg_freeaddrinfo_all(hints.ai_family, la);
1505                 return false;                   /* we don't expect this to happen */
1506         }
1507
1508         sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1509                                          ident_serv->ai_protocol);
1510         if (sock_fd < 0)
1511         {
1512                 ereport(LOG,
1513                                 (errcode_for_socket_access(),
1514                                  errmsg("could not create socket for Ident connection: %m")));
1515                 ident_return = false;
1516                 goto ident_inet_done;
1517         }
1518
1519         /*
1520          * Bind to the address which the client originally contacted, otherwise
1521          * the ident server won't be able to match up the right connection. This
1522          * is necessary if the PostgreSQL server is running on an IP alias.
1523          */
1524         rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1525         if (rc != 0)
1526         {
1527                 ereport(LOG,
1528                                 (errcode_for_socket_access(),
1529                                  errmsg("could not bind to local address \"%s\": %m",
1530                                                 local_addr_s)));
1531                 ident_return = false;
1532                 goto ident_inet_done;
1533         }
1534
1535         rc = connect(sock_fd, ident_serv->ai_addr,
1536                                  ident_serv->ai_addrlen);
1537         if (rc != 0)
1538         {
1539                 ereport(LOG,
1540                                 (errcode_for_socket_access(),
1541                                  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1542                                                 remote_addr_s, ident_port)));
1543                 ident_return = false;
1544                 goto ident_inet_done;
1545         }
1546
1547         /* The query we send to the Ident server */
1548         snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1549                          remote_port, local_port);
1550
1551         /* loop in case send is interrupted */
1552         do
1553         {
1554                 rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1555         } while (rc < 0 && errno == EINTR);
1556
1557         if (rc < 0)
1558         {
1559                 ereport(LOG,
1560                                 (errcode_for_socket_access(),
1561                                  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1562                                                 remote_addr_s, ident_port)));
1563                 ident_return = false;
1564                 goto ident_inet_done;
1565         }
1566
1567         do
1568         {
1569                 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1570         } while (rc < 0 && errno == EINTR);
1571
1572         if (rc < 0)
1573         {
1574                 ereport(LOG,
1575                                 (errcode_for_socket_access(),
1576                                  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1577                                                 remote_addr_s, ident_port)));
1578                 ident_return = false;
1579                 goto ident_inet_done;
1580         }
1581
1582         ident_response[rc] = '\0';
1583         ident_return = interpret_ident_response(ident_response, ident_user);
1584         if (!ident_return)
1585                 ereport(LOG,
1586                         (errmsg("invalidly formatted response from Ident server: \"%s\"",
1587                                         ident_response)));
1588
1589 ident_inet_done:
1590         if (sock_fd >= 0)
1591                 closesocket(sock_fd);
1592         pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1593         pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1594         return ident_return;
1595 }
1596
1597 /*
1598  *      Ask kernel about the credentials of the connecting process and
1599  *      determine the symbolic name of the corresponding user.
1600  *
1601  *      Returns either true and the username put into "ident_user",
1602  *      or false if we were unable to determine the username.
1603  */
1604 #ifdef HAVE_UNIX_SOCKETS
1605
1606 static bool
1607 ident_unix(int sock, char *ident_user)
1608 {
1609 #if defined(HAVE_GETPEEREID)
1610         /* OpenBSD style:  */
1611         uid_t           uid;
1612         gid_t           gid;
1613         struct passwd *pass;
1614
1615         errno = 0;
1616         if (getpeereid(sock, &uid, &gid) != 0)
1617         {
1618                 /* We didn't get a valid credentials struct. */
1619                 ereport(LOG,
1620                                 (errcode_for_socket_access(),
1621                                  errmsg("could not get peer credentials: %m")));
1622                 return false;
1623         }
1624
1625         pass = getpwuid(uid);
1626
1627         if (pass == NULL)
1628         {
1629                 ereport(LOG,
1630                                 (errmsg("local user with ID %d does not exist",
1631                                                 (int) uid)));
1632                 return false;
1633         }
1634
1635         strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
1636
1637         return true;
1638 #elif defined(SO_PEERCRED)
1639         /* Linux style: use getsockopt(SO_PEERCRED) */
1640         struct ucred peercred;
1641         ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
1642         struct passwd *pass;
1643
1644         errno = 0;
1645         if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
1646                 so_len != sizeof(peercred))
1647         {
1648                 /* We didn't get a valid credentials struct. */
1649                 ereport(LOG,
1650                                 (errcode_for_socket_access(),
1651                                  errmsg("could not get peer credentials: %m")));
1652                 return false;
1653         }
1654
1655         pass = getpwuid(peercred.uid);
1656
1657         if (pass == NULL)
1658         {
1659                 ereport(LOG,
1660                                 (errmsg("local user with ID %d does not exist",
1661                                                 (int) peercred.uid)));
1662                 return false;
1663         }
1664
1665         strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
1666
1667         return true;
1668 #elif defined(HAVE_GETPEERUCRED)
1669         /* Solaris > 10 */
1670         uid_t           uid;
1671         struct passwd *pass;
1672         ucred_t    *ucred;
1673
1674         ucred = NULL; /* must be initialized to NULL */
1675         if (getpeerucred(sock, &ucred) == -1)
1676         {
1677                 ereport(LOG,
1678                                 (errcode_for_socket_access(),
1679                                  errmsg("could not get peer credentials: %m")));
1680                 return false;
1681         }
1682
1683         if ((uid = ucred_geteuid(ucred)) == -1)
1684         {
1685                 ereport(LOG,
1686                                 (errcode_for_socket_access(),
1687                                  errmsg("could not get effective UID from peer credentials: %m")));
1688                 return false;
1689         }
1690
1691         ucred_free(ucred);
1692
1693         pass = getpwuid(uid);
1694         if (pass == NULL)
1695         {
1696                 ereport(LOG,
1697                         (errmsg("local user with ID %d does not exist",
1698                                         (int) uid)));
1699                 return false;
1700         }
1701
1702         strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
1703
1704         return true;
1705 #elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
1706         struct msghdr msg;
1707
1708 /* Credentials structure */
1709 #if defined(HAVE_STRUCT_CMSGCRED)
1710         typedef struct cmsgcred Cred;
1711
1712 #define cruid cmcred_uid
1713 #elif defined(HAVE_STRUCT_FCRED)
1714         typedef struct fcred Cred;
1715
1716 #define cruid fc_uid
1717 #elif defined(HAVE_STRUCT_SOCKCRED)
1718         typedef struct sockcred Cred;
1719
1720 #define cruid sc_uid
1721 #endif
1722         Cred       *cred;
1723
1724         /* Compute size without padding */
1725         char            cmsgmem[ALIGN(sizeof(struct cmsghdr)) + ALIGN(sizeof(Cred))];   /* for NetBSD */
1726
1727         /* Point to start of first structure */
1728         struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
1729
1730         struct iovec iov;
1731         char            buf;
1732         struct passwd *pw;
1733
1734         memset(&msg, 0, sizeof(msg));
1735         msg.msg_iov = &iov;
1736         msg.msg_iovlen = 1;
1737         msg.msg_control = (char *) cmsg;
1738         msg.msg_controllen = sizeof(cmsgmem);
1739         memset(cmsg, 0, sizeof(cmsgmem));
1740
1741         /*
1742          * The one character which is received here is not meaningful; its
1743          * purposes is only to make sure that recvmsg() blocks long enough for the
1744          * other side to send its credentials.
1745          */
1746         iov.iov_base = &buf;
1747         iov.iov_len = 1;
1748
1749         if (recvmsg(sock, &msg, 0) < 0 ||
1750                 cmsg->cmsg_len < sizeof(cmsgmem) ||
1751                 cmsg->cmsg_type != SCM_CREDS)
1752         {
1753                 ereport(LOG,
1754                                 (errcode_for_socket_access(),
1755                                  errmsg("could not get peer credentials: %m")));
1756                 return false;
1757         }
1758
1759         cred = (Cred *) CMSG_DATA(cmsg);
1760
1761         pw = getpwuid(cred->cruid);
1762
1763         if (pw == NULL)
1764         {
1765                 ereport(LOG,
1766                                 (errmsg("local user with ID %d does not exist",
1767                                                 (int) cred->cruid)));
1768                 return false;
1769         }
1770
1771         strlcpy(ident_user, pw->pw_name, IDENT_USERNAME_MAX + 1);
1772
1773         return true;
1774 #else
1775         ereport(LOG,
1776                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1777                          errmsg("Ident authentication is not supported on local connections on this platform")));
1778
1779         return false;
1780 #endif
1781 }
1782 #endif   /* HAVE_UNIX_SOCKETS */
1783
1784
1785 /*
1786  *      Determine the username of the initiator of the connection described
1787  *      by "port".      Then look in the usermap file under the usermap
1788  *      port->hba->usermap and see if that user is equivalent to Postgres user
1789  *      port->user.
1790  *
1791  *      Return STATUS_OK if yes, STATUS_ERROR if no match (or couldn't get info).
1792  */
1793 static int
1794 authident(hbaPort *port)
1795 {
1796         char            ident_user[IDENT_USERNAME_MAX + 1];
1797
1798         if (get_role_line(port->user_name) == NULL)
1799                 return STATUS_ERROR;
1800
1801         switch (port->raddr.addr.ss_family)
1802         {
1803                 case AF_INET:
1804 #ifdef  HAVE_IPV6
1805                 case AF_INET6:
1806 #endif
1807                         if (!ident_inet(port->raddr, port->laddr, ident_user))
1808                                 return STATUS_ERROR;
1809                         break;
1810
1811 #ifdef HAVE_UNIX_SOCKETS
1812                 case AF_UNIX:
1813                         if (!ident_unix(port->sock, ident_user))
1814                                 return STATUS_ERROR;
1815                         break;
1816 #endif
1817
1818                 default:
1819                         return STATUS_ERROR;
1820         }
1821
1822         return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1823 }
1824
1825
1826 /*----------------------------------------------------------------
1827  * PAM authentication system
1828  *----------------------------------------------------------------
1829  */
1830 #ifdef USE_PAM
1831
1832 /*
1833  * PAM conversation function
1834  */
1835
1836 static int
1837 pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
1838                                          struct pam_response ** resp, void *appdata_ptr)
1839 {
1840         if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
1841         {
1842                 switch (msg[0]->msg_style)
1843                 {
1844                         case PAM_ERROR_MSG:
1845                                 ereport(LOG,
1846                                                 (errmsg("error from underlying PAM layer: %s",
1847                                                                 msg[0]->msg)));
1848                                 return PAM_CONV_ERR;
1849                         default:
1850                                 ereport(LOG,
1851                                                 (errmsg("unsupported PAM conversation %d/%s",
1852                                                                 msg[0]->msg_style, msg[0]->msg)));
1853                                 return PAM_CONV_ERR;
1854                 }
1855         }
1856
1857         if (!appdata_ptr)
1858         {
1859                 /*
1860                  * Workaround for Solaris 2.6 where the PAM library is broken and does
1861                  * not pass appdata_ptr to the conversation routine
1862                  */
1863                 appdata_ptr = pam_passwd;
1864         }
1865
1866         /*
1867          * Password wasn't passed to PAM the first time around - let's go ask the
1868          * client to send a password, which we then stuff into PAM.
1869          */
1870         if (strlen(appdata_ptr) == 0)
1871         {
1872                 char       *passwd;
1873
1874                 sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);
1875                 passwd = recv_password_packet(pam_port_cludge);
1876
1877                 if (passwd == NULL)
1878                         return PAM_CONV_ERR;    /* client didn't want to send password */
1879
1880                 if (strlen(passwd) == 0)
1881                 {
1882                         ereport(LOG,
1883                                         (errmsg("empty password returned by client")));
1884                         return PAM_CONV_ERR;
1885                 }
1886                 appdata_ptr = passwd;
1887         }
1888
1889         /*
1890          * Explicitly not using palloc here - PAM will free this memory in
1891          * pam_end()
1892          */
1893         *resp = calloc(num_msg, sizeof(struct pam_response));
1894         if (!*resp)
1895         {
1896                 ereport(LOG,
1897                                 (errcode(ERRCODE_OUT_OF_MEMORY),
1898                                  errmsg("out of memory")));
1899                 return PAM_CONV_ERR;
1900         }
1901
1902         (*resp)[0].resp = strdup((char *) appdata_ptr);
1903         (*resp)[0].resp_retcode = 0;
1904
1905         return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
1906 }
1907
1908
1909 /*
1910  * Check authentication against PAM.
1911  */
1912 static int
1913 CheckPAMAuth(Port *port, char *user, char *password)
1914 {
1915         int                     retval;
1916         pam_handle_t *pamh = NULL;
1917
1918         /*
1919          * Apparently, Solaris 2.6 is broken, and needs ugly static variable
1920          * workaround
1921          */
1922         pam_passwd = password;
1923
1924         /*
1925          * Set the application data portion of the conversation struct This is
1926          * later used inside the PAM conversation to pass the password to the
1927          * authentication module.
1928          */
1929         pam_passw_conv.appdata_ptr = (char *) password;         /* from password above,
1930                                                                                                                  * not allocated */
1931
1932         /* Optionally, one can set the service name in pg_hba.conf */
1933         if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
1934                 retval = pam_start(port->hba->pamservice, "pgsql@",
1935                                                    &pam_passw_conv, &pamh);
1936         else
1937                 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
1938                                                    &pam_passw_conv, &pamh);
1939
1940         if (retval != PAM_SUCCESS)
1941         {
1942                 ereport(LOG,
1943                                 (errmsg("could not create PAM authenticator: %s",
1944                                                 pam_strerror(pamh, retval))));
1945                 pam_passwd = NULL;              /* Unset pam_passwd */
1946                 return STATUS_ERROR;
1947         }
1948
1949         retval = pam_set_item(pamh, PAM_USER, user);
1950
1951         if (retval != PAM_SUCCESS)
1952         {
1953                 ereport(LOG,
1954                                 (errmsg("pam_set_item(PAM_USER) failed: %s",
1955                                                 pam_strerror(pamh, retval))));
1956                 pam_passwd = NULL;              /* Unset pam_passwd */
1957                 return STATUS_ERROR;
1958         }
1959
1960         retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
1961
1962         if (retval != PAM_SUCCESS)
1963         {
1964                 ereport(LOG,
1965                                 (errmsg("pam_set_item(PAM_CONV) failed: %s",
1966                                                 pam_strerror(pamh, retval))));
1967                 pam_passwd = NULL;              /* Unset pam_passwd */
1968                 return STATUS_ERROR;
1969         }
1970
1971         retval = pam_authenticate(pamh, 0);
1972
1973         if (retval != PAM_SUCCESS)
1974         {
1975                 ereport(LOG,
1976                                 (errmsg("pam_authenticate failed: %s",
1977                                                 pam_strerror(pamh, retval))));
1978                 pam_passwd = NULL;              /* Unset pam_passwd */
1979                 return STATUS_ERROR;
1980         }
1981
1982         retval = pam_acct_mgmt(pamh, 0);
1983
1984         if (retval != PAM_SUCCESS)
1985         {
1986                 ereport(LOG,
1987                                 (errmsg("pam_acct_mgmt failed: %s",
1988                                                 pam_strerror(pamh, retval))));
1989                 pam_passwd = NULL;              /* Unset pam_passwd */
1990                 return STATUS_ERROR;
1991         }
1992
1993         retval = pam_end(pamh, retval);
1994
1995         if (retval != PAM_SUCCESS)
1996         {
1997                 ereport(LOG,
1998                                 (errmsg("could not release PAM authenticator: %s",
1999                                                 pam_strerror(pamh, retval))));
2000         }
2001
2002         pam_passwd = NULL;                      /* Unset pam_passwd */
2003
2004         return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
2005 }
2006 #endif   /* USE_PAM */
2007
2008
2009
2010 /*----------------------------------------------------------------
2011  * LDAP authentication system
2012  *----------------------------------------------------------------
2013  */
2014 #ifdef USE_LDAP
2015
2016 static int
2017 CheckLDAPAuth(Port *port)
2018 {
2019         char       *passwd;
2020         LDAP       *ldap;
2021         int                     r;
2022         int                     ldapversion = LDAP_VERSION3;
2023         char            fulluser[NAMEDATALEN + 256 + 1];
2024
2025         if (!port->hba->ldapserver|| port->hba->ldapserver[0] == '\0')
2026         {
2027                 ereport(LOG,
2028                                 (errmsg("LDAP server not specified")));
2029                 return STATUS_ERROR;
2030         }
2031
2032         if (port->hba->ldapport == 0)
2033                 port->hba->ldapport = LDAP_PORT;
2034
2035         sendAuthRequest(port, AUTH_REQ_PASSWORD);
2036
2037         passwd = recv_password_packet(port);
2038         if (passwd == NULL)
2039                 return STATUS_EOF;              /* client wouldn't send password */
2040
2041         ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2042         if (!ldap)
2043         {
2044 #ifndef WIN32
2045                 ereport(LOG,
2046                                 (errmsg("could not initialize LDAP: error code %d",
2047                                                 errno)));
2048 #else
2049                 ereport(LOG,
2050                                 (errmsg("could not initialize LDAP: error code %d",
2051                                                 (int) LdapGetLastError())));
2052 #endif
2053                 return STATUS_ERROR;
2054         }
2055
2056         if ((r = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
2057         {
2058                 ldap_unbind(ldap);
2059                 ereport(LOG,
2060                   (errmsg("could not set LDAP protocol version: error code %d", r)));
2061                 return STATUS_ERROR;
2062         }
2063
2064         if (port->hba->ldaptls)
2065         {
2066 #ifndef WIN32
2067                 if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
2068 #else
2069                 static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
2070
2071                 if (_ldap_start_tls_sA == NULL)
2072                 {
2073                         /*
2074                          * Need to load this function dynamically because it does not
2075                          * exist on Windows 2000, and causes a load error for the whole
2076                          * exe if referenced.
2077                          */
2078                         HANDLE          ldaphandle;
2079
2080                         ldaphandle = LoadLibrary("WLDAP32.DLL");
2081                         if (ldaphandle == NULL)
2082                         {
2083                                 /*
2084                                  * should never happen since we import other files from
2085                                  * wldap32, but check anyway
2086                                  */
2087                                 ldap_unbind(ldap);
2088                                 ereport(LOG,
2089                                                 (errmsg("could not load wldap32.dll")));
2090                                 return STATUS_ERROR;
2091                         }
2092                         _ldap_start_tls_sA = (__ldap_start_tls_sA) GetProcAddress(ldaphandle, "ldap_start_tls_sA");
2093                         if (_ldap_start_tls_sA == NULL)
2094                         {
2095                                 ldap_unbind(ldap);
2096                                 ereport(LOG,
2097                                                 (errmsg("could not load function _ldap_start_tls_sA in wldap32.dll"),
2098                                                  errdetail("LDAP over SSL is not supported on this platform.")));
2099                                 return STATUS_ERROR;
2100                         }
2101
2102                         /*
2103                          * Leak LDAP handle on purpose, because we need the library to
2104                          * stay open. This is ok because it will only ever be leaked once
2105                          * per process and is automatically cleaned up on process exit.
2106                          */
2107                 }
2108                 if ((r = _ldap_start_tls_sA(ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
2109 #endif
2110                 {
2111                         ldap_unbind(ldap);
2112                         ereport(LOG,
2113                          (errmsg("could not start LDAP TLS session: error code %d", r)));
2114                         return STATUS_ERROR;
2115                 }
2116         }
2117
2118         snprintf(fulluser, sizeof(fulluser), "%s%s%s",
2119                          port->hba->ldapprefix ? port->hba->ldapprefix : "",
2120                          port->user_name,
2121                          port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
2122         fulluser[sizeof(fulluser) - 1] = '\0';
2123
2124         r = ldap_simple_bind_s(ldap, fulluser, passwd);
2125         ldap_unbind(ldap);
2126
2127         if (r != LDAP_SUCCESS)
2128         {
2129                 ereport(LOG,
2130                                 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
2131                                                 fulluser, port->hba->ldapserver, r)));
2132                 return STATUS_ERROR;
2133         }
2134
2135         return STATUS_OK;
2136 }
2137 #endif   /* USE_LDAP */
2138
2139
2140 /*----------------------------------------------------------------
2141  * SSL client certificate authentication
2142  *----------------------------------------------------------------
2143  */
2144 #ifdef USE_SSL
2145 static int
2146 CheckCertAuth(Port *port)
2147 {
2148         Assert(port->ssl);
2149
2150         /* Make sure we have received a username in the certificate */
2151         if (port->peer_cn == NULL ||
2152                 strlen(port->peer_cn) <= 0)
2153         {
2154                 ereport(LOG,
2155                                 (errmsg("Certificate login failed for user \"%s\": client certificate contains no username",
2156                                                 port->user_name)));
2157                 return STATUS_ERROR;
2158         }
2159
2160         /* Just pass the certificate CN to the usermap check */
2161         return check_usermap(port->hba->usermap, port->user_name, port->peer_cn, false);
2162 }
2163 #endif