]> granicus.if.org Git - postgresql/blob - src/backend/libpq/auth.c
SSPI authentication on Windows. GSSAPI compatible client when doing Kerberos
[postgresql] / src / backend / libpq / auth.c
1 /*-------------------------------------------------------------------------
2  *
3  * auth.c
4  *        Routines to handle network authentication
5  *
6  * Portions Copyright (c) 1996-2007, 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.154 2007/07/23 10:16:53 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 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <unistd.h>
27
28 #include "libpq/auth.h"
29 #include "libpq/crypt.h"
30 #include "libpq/ip.h"
31 #include "libpq/libpq.h"
32 #include "libpq/pqformat.h"
33 #include "storage/ipc.h"
34
35
36 static void sendAuthRequest(Port *port, AuthRequest areq);
37 static void auth_failed(Port *port, int status);
38 static char *recv_password_packet(Port *port);
39 static int      recv_and_check_password_packet(Port *port);
40
41 char       *pg_krb_server_keyfile;
42 char       *pg_krb_srvnam;
43 bool            pg_krb_caseins_users;
44 char       *pg_krb_server_hostname = NULL;
45
46 #ifdef USE_PAM
47 #ifdef HAVE_PAM_PAM_APPL_H
48 #include <pam/pam_appl.h>
49 #endif
50 #ifdef HAVE_SECURITY_PAM_APPL_H
51 #include <security/pam_appl.h>
52 #endif
53
54 #define PGSQL_PAM_SERVICE "postgresql"  /* Service name passed to PAM */
55
56 static int      CheckPAMAuth(Port *port, char *user, char *password);
57 static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
58                                          struct pam_response ** resp, void *appdata_ptr);
59
60 static struct pam_conv pam_passw_conv = {
61         &pam_passwd_conv_proc,
62         NULL
63 };
64
65 static char *pam_passwd = NULL; /* Workaround for Solaris 2.6 brokenness */
66 static Port *pam_port_cludge;   /* Workaround for passing "Port *port" into
67                                                                  * pam_passwd_conv_proc */
68 #endif   /* USE_PAM */
69
70 #ifdef USE_LDAP
71 #ifndef WIN32
72 /* We use a deprecated function to keep the codepath the same as win32. */
73 #define LDAP_DEPRECATED 1
74 #include <ldap.h>
75 #else
76 #include <winldap.h>
77
78 /* Correct header from the Platform SDK */
79 typedef
80 ULONG(*__ldap_start_tls_sA) (
81                                                          IN PLDAP ExternalHandle,
82                                                          OUT PULONG ServerReturnValue,
83                                                          OUT LDAPMessage ** result,
84                                                          IN PLDAPControlA * ServerControls,
85                                                          IN PLDAPControlA * ClientControls
86 );
87 #endif
88
89 static int      CheckLDAPAuth(Port *port);
90 #endif
91
92
93 #ifdef KRB5
94 /*----------------------------------------------------------------
95  * MIT Kerberos authentication system - protocol version 5
96  *----------------------------------------------------------------
97  */
98
99 #include <krb5.h>
100 /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
101 #if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
102 #include <com_err.h>
103 #endif
104
105 /*
106  * pg_an_to_ln -- return the local name corresponding to an authentication
107  *                                name
108  *
109  * XXX Assumes that the first aname component is the user name.  This is NOT
110  *         necessarily so, since an aname can actually be something out of your
111  *         worst X.400 nightmare, like
112  *                ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
113  *         Note that the MIT an_to_ln code does the same thing if you don't
114  *         provide an aname mapping database...it may be a better idea to use
115  *         krb5_an_to_ln, except that it punts if multiple components are found,
116  *         and we can't afford to punt.
117  */
118 static char *
119 pg_an_to_ln(char *aname)
120 {
121         char       *p;
122
123         if ((p = strchr(aname, '/')) || (p = strchr(aname, '@')))
124                 *p = '\0';
125         return aname;
126 }
127
128
129 /*
130  * Various krb5 state which is not connection specfic, and a flag to
131  * indicate whether we have initialised it yet.
132  */
133 static int      pg_krb5_initialised;
134 static krb5_context pg_krb5_context;
135 static krb5_keytab pg_krb5_keytab;
136 static krb5_principal pg_krb5_server;
137
138
139 static int
140 pg_krb5_init(void)
141 {
142         krb5_error_code retval;
143         char       *khostname;
144
145         if (pg_krb5_initialised)
146                 return STATUS_OK;
147
148         retval = krb5_init_context(&pg_krb5_context);
149         if (retval)
150         {
151                 ereport(LOG,
152                                 (errmsg("Kerberos initialization returned error %d",
153                                                 retval)));
154                 com_err("postgres", retval, "while initializing krb5");
155                 return STATUS_ERROR;
156         }
157
158         retval = krb5_kt_resolve(pg_krb5_context, pg_krb_server_keyfile, &pg_krb5_keytab);
159         if (retval)
160         {
161                 ereport(LOG,
162                                 (errmsg("Kerberos keytab resolving returned error %d",
163                                                 retval)));
164                 com_err("postgres", retval, "while resolving keytab file \"%s\"",
165                                 pg_krb_server_keyfile);
166                 krb5_free_context(pg_krb5_context);
167                 return STATUS_ERROR;
168         }
169
170         /*
171          * If no hostname was specified, pg_krb_server_hostname is already NULL.
172          * If it's set to blank, force it to NULL.
173          */
174         khostname = pg_krb_server_hostname;
175         if (khostname && khostname[0] == '\0')
176                 khostname = NULL;
177
178         retval = krb5_sname_to_principal(pg_krb5_context,
179                                                                          khostname,
180                                                                          pg_krb_srvnam,
181                                                                          KRB5_NT_SRV_HST,
182                                                                          &pg_krb5_server);
183         if (retval)
184         {
185                 ereport(LOG,
186                                 (errmsg("Kerberos sname_to_principal(\"%s\", \"%s\") returned error %d",
187                  khostname ? khostname : "server hostname", pg_krb_srvnam, retval)));
188                 com_err("postgres", retval,
189                 "while getting server principal for server \"%s\" for service \"%s\"",
190                                 khostname ? khostname : "server hostname", pg_krb_srvnam);
191                 krb5_kt_close(pg_krb5_context, pg_krb5_keytab);
192                 krb5_free_context(pg_krb5_context);
193                 return STATUS_ERROR;
194         }
195
196         pg_krb5_initialised = 1;
197         return STATUS_OK;
198 }
199
200
201 /*
202  * pg_krb5_recvauth -- server routine to receive authentication information
203  *                                         from the client
204  *
205  * We still need to compare the username obtained from the client's setup
206  * packet to the authenticated name.
207  *
208  * We have our own keytab file because postgres is unlikely to run as root,
209  * and so cannot read the default keytab.
210  */
211 static int
212 pg_krb5_recvauth(Port *port)
213 {
214         krb5_error_code retval;
215         int                     ret;
216         krb5_auth_context auth_context = NULL;
217         krb5_ticket *ticket;
218         char       *kusername;
219
220         if (get_role_line(port->user_name) == NULL)
221                 return STATUS_ERROR;
222         
223         ret = pg_krb5_init();
224         if (ret != STATUS_OK)
225                 return ret;
226
227         retval = krb5_recvauth(pg_krb5_context, &auth_context,
228                                                    (krb5_pointer) & port->sock, pg_krb_srvnam,
229                                                    pg_krb5_server, 0, pg_krb5_keytab, &ticket);
230         if (retval)
231         {
232                 ereport(LOG,
233                                 (errmsg("Kerberos recvauth returned error %d",
234                                                 retval)));
235                 com_err("postgres", retval, "from krb5_recvauth");
236                 return STATUS_ERROR;
237         }
238
239         /*
240          * The "client" structure comes out of the ticket and is therefore
241          * authenticated.  Use it to check the username obtained from the
242          * postmaster startup packet.
243          *
244          * I have no idea why this is considered necessary.
245          */
246 #if defined(HAVE_KRB5_TICKET_ENC_PART2)
247         retval = krb5_unparse_name(pg_krb5_context,
248                                                            ticket->enc_part2->client, &kusername);
249 #elif defined(HAVE_KRB5_TICKET_CLIENT)
250         retval = krb5_unparse_name(pg_krb5_context,
251                                                            ticket->client, &kusername);
252 #else
253 #error "bogus configuration"
254 #endif
255         if (retval)
256         {
257                 ereport(LOG,
258                                 (errmsg("Kerberos unparse_name returned error %d",
259                                                 retval)));
260                 com_err("postgres", retval, "while unparsing client name");
261                 krb5_free_ticket(pg_krb5_context, ticket);
262                 krb5_auth_con_free(pg_krb5_context, auth_context);
263                 return STATUS_ERROR;
264         }
265
266         kusername = pg_an_to_ln(kusername);
267         if (pg_krb_caseins_users)
268                 ret = pg_strncasecmp(port->user_name, kusername, SM_DATABASE_USER);
269         else
270                 ret = strncmp(port->user_name, kusername, SM_DATABASE_USER);
271         if (ret)
272         {
273                 ereport(LOG,
274                                 (errmsg("unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")",
275                                                 port->user_name, kusername)));
276                 ret = STATUS_ERROR;
277         }
278         else
279                 ret = STATUS_OK;
280
281         krb5_free_ticket(pg_krb5_context, ticket);
282         krb5_auth_con_free(pg_krb5_context, auth_context);
283         free(kusername);
284
285         return ret;
286 }
287 #else
288
289 static int
290 pg_krb5_recvauth(Port *port)
291 {
292         ereport(LOG,
293                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
294                          errmsg("Kerberos 5 not implemented on this server")));
295         return STATUS_ERROR;
296 }
297 #endif   /* KRB5 */
298
299 #ifdef ENABLE_GSS
300 /*----------------------------------------------------------------
301  * GSSAPI authentication system
302  *----------------------------------------------------------------
303  */
304
305 #if defined(HAVE_GSSAPI_H)
306 #include <gssapi.h>
307 #else
308 #include <gssapi/gssapi.h>
309 #endif
310
311 #if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
312 /*
313  * MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
314  * that contain the OIDs required. Redefine here, values copied
315  * from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
316  */
317 static const gss_OID_desc GSS_C_NT_USER_NAME_desc =
318  {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"};
319 static GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_desc;
320 #endif
321
322
323 static void
324 pg_GSS_error(int severity, char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
325 {
326         gss_buffer_desc gmsg;
327         OM_uint32               lmaj_s, lmin_s, msg_ctx;
328         char                    msg_major[128],
329                                         msg_minor[128];
330
331         /* Fetch major status message */
332         msg_ctx = 0;
333         lmaj_s = gss_display_status(&lmin_s, maj_stat, GSS_C_GSS_CODE,
334                         GSS_C_NO_OID, &msg_ctx, &gmsg);
335         strlcpy(msg_major, gmsg.value, sizeof(msg_major));
336         gss_release_buffer(&lmin_s, &gmsg);
337
338         if (msg_ctx)
339                 /* More than one message available.
340                  * XXX: Should we loop and read all messages?
341                  * (same below)
342                  */
343                 ereport(WARNING, 
344                                 (errmsg_internal("incomplete GSS error report")));
345
346         /* Fetch mechanism minor status message */
347         msg_ctx = 0;
348         lmaj_s = gss_display_status(&lmin_s, min_stat, GSS_C_MECH_CODE,
349                         GSS_C_NO_OID, &msg_ctx, &gmsg);
350         strlcpy(msg_minor, gmsg.value, sizeof(msg_minor));
351         gss_release_buffer(&lmin_s, &gmsg);
352
353         if (msg_ctx)
354                 ereport(WARNING,
355                                 (errmsg_internal("incomplete GSS minor error report")));
356
357         /* errmsg_internal, since translation of the first part must be
358          * done before calling this function anyway. */
359         ereport(severity,
360                         (errmsg_internal("%s", errmsg),
361                          errdetail("%s: %s", msg_major, msg_minor)));
362 }
363
364 static int
365 pg_GSS_recvauth(Port *port)
366 {
367         OM_uint32               maj_stat, min_stat, lmin_s, gflags;
368         char               *kt_path;
369         int                             mtype;
370         int                             ret;
371         StringInfoData  buf;
372         gss_buffer_desc gbuf;
373
374         if (pg_krb_server_keyfile && strlen(pg_krb_server_keyfile) > 0)
375         {
376                 /*
377                  * Set default Kerberos keytab file for the Krb5 mechanism.
378                  *
379                  * setenv("KRB5_KTNAME", pg_krb_server_keyfile, 0);
380                  *              except setenv() not always available.
381                  */
382                 if (!getenv("KRB5_KTNAME"))
383                 {
384                         kt_path = palloc(MAXPGPATH + 13);
385                         snprintf(kt_path, MAXPGPATH + 13,
386                                         "KRB5_KTNAME=%s", pg_krb_server_keyfile);
387                         putenv(kt_path);
388                 }
389         }
390
391         /*
392          * We accept any service principal that's present in our
393          * keytab. This increases interoperability between kerberos
394          * implementations that see for example case sensitivity
395          * differently, while not really opening up any vector
396          * of attack.
397          */
398         port->gss->cred = GSS_C_NO_CREDENTIAL;
399
400         /*
401          * Initialize sequence with an empty context
402          */
403         port->gss->ctx = GSS_C_NO_CONTEXT;
404
405         /*
406          * Loop through GSSAPI message exchange. This exchange can consist
407          * of multiple messags sent in both directions. First message is always
408          * from the client. All messages from client to server are password
409          * packets (type 'p').
410          */
411         do 
412         {
413                 mtype = pq_getbyte();
414                 if (mtype != 'p')
415                 {
416                         /* Only log error if client didn't disconnect. */
417                         if (mtype != EOF)
418                                 ereport(COMMERROR,
419                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
420                                                  errmsg("expected GSS response, got message type %d",
421                                                          mtype)));
422                         return STATUS_ERROR;
423                 }
424
425                 /* Get the actual GSS token */
426                 initStringInfo(&buf);
427                 if (pq_getmessage(&buf, 2000))
428                 {
429                         /* EOF - pq_getmessage already logged error */
430                         pfree(buf.data);
431                         return STATUS_ERROR;
432                 }
433
434                 /* Map to GSSAPI style buffer */
435                 gbuf.length = buf.len;
436                 gbuf.value = buf.data;
437
438                 elog(DEBUG4, "Processing received GSS token of length %u", 
439                          (unsigned int) gbuf.length);
440
441                 maj_stat = gss_accept_sec_context(
442                                 &min_stat,
443                                 &port->gss->ctx,
444                                 port->gss->cred,
445                                 &gbuf,
446                                 GSS_C_NO_CHANNEL_BINDINGS,
447                                 &port->gss->name,
448                                 NULL,
449                                 &port->gss->outbuf,
450                                 &gflags,
451                                 NULL,
452                                 NULL);
453
454                 /* gbuf no longer used */
455                 pfree(buf.data);
456
457                 elog(DEBUG5, "gss_accept_sec_context major: %d, "
458                          "minor: %d, outlen: %u, outflags: %x",
459                          maj_stat, min_stat,
460                          (unsigned int) port->gss->outbuf.length, gflags);
461
462                 if (port->gss->outbuf.length != 0)
463                 {
464                         /*
465                          * Negotiation generated data to be sent to the client.
466                          */
467                         OM_uint32       lmin_s;
468
469                         elog(DEBUG4, "sending GSS response token of length %u",
470                                  (unsigned int) port->gss->outbuf.length);
471
472                         sendAuthRequest(port, AUTH_REQ_GSS_CONT);
473
474                         gss_release_buffer(&lmin_s, &port->gss->outbuf);
475                 }
476
477                 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
478                 {
479                         OM_uint32       lmin_s;
480                         gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
481                         pg_GSS_error(ERROR, 
482                                         gettext_noop("accepting GSS security context failed"),
483                                         maj_stat, min_stat);
484                 }
485
486                 if (maj_stat == GSS_S_CONTINUE_NEEDED)
487                         elog(DEBUG4, "GSS continue needed");
488
489         } while (maj_stat == GSS_S_CONTINUE_NEEDED);
490
491         if (port->gss->cred != GSS_C_NO_CREDENTIAL)
492         {
493                 /*
494                  * Release service principal credentials
495                  */
496                 gss_release_cred(&min_stat, port->gss->cred);
497         }
498
499         /*
500          * GSS_S_COMPLETE indicates that authentication is now complete.
501          *
502          * Get the name of the user that authenticated, and compare it to the
503          * pg username that was specified for the connection.
504          */
505         maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
506         if (maj_stat != GSS_S_COMPLETE)
507                 pg_GSS_error(ERROR,
508                                          gettext_noop("retreiving GSS user name failed"),
509                                          maj_stat, min_stat);
510
511         /*
512          * Compare the part of the username that comes before the @
513          * sign only (ignore realm). The GSSAPI libraries won't have 
514          * authenticated the user if he's from an invalid realm.
515          */
516         if (strchr(gbuf.value, '@'))
517         {
518                 char *cp = strchr(gbuf.value, '@');
519                 *cp = '\0';
520         }
521
522         if (pg_krb_caseins_users)
523                 ret = pg_strcasecmp(port->user_name, gbuf.value);
524         else
525                 ret = strcmp(port->user_name, gbuf.value);
526
527         if (ret)
528         {
529                 /* GSS name and PGUSER are not equivalent */
530                 elog(DEBUG2, 
531                          "provided username (%s) and GSSAPI username (%s) don't match",
532                          port->user_name, (char *)gbuf.value);
533
534                 gss_release_buffer(&lmin_s, &gbuf);
535                 return STATUS_ERROR;
536         }
537         
538         gss_release_buffer(&lmin_s, &gbuf);
539
540         return STATUS_OK;
541 }
542
543 #else /* no ENABLE_GSS */
544 static int
545 pg_GSS_recvauth(Port *port)
546 {
547         ereport(LOG,
548                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
549                          errmsg("GSSAPI not implemented on this server.")));
550         return STATUS_ERROR;
551 }
552 #endif  /* ENABLE_GSS */
553
554 #ifdef ENABLE_SSPI
555 static void
556 pg_SSPI_error(int severity, char *errmsg, SECURITY_STATUS r)
557 {
558         char sysmsg[256];
559
560         if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, r, 0, sysmsg, sizeof(sysmsg), NULL) == 0)
561                 ereport(severity,
562                         (errmsg_internal("%s", errmsg),
563                                 errdetail("sspi error %x", r)));
564         else
565                 ereport(severity,
566                         (errmsg_internal("%s", errmsg),
567                                 errdetail("%s (%x)", sysmsg, r)));
568 }
569
570
571 static int
572 pg_SSPI_recvauth(Port *port)
573 {
574         int                             mtype;
575         StringInfoData  buf;
576         SECURITY_STATUS r;
577         CredHandle              sspicred;
578         CtxtHandle              *sspictx = NULL,
579                             newctx;
580         TimeStamp               expiry;
581         ULONG                   contextattr;
582         SecBufferDesc   inbuf;
583         SecBufferDesc   outbuf;
584         SecBuffer               OutBuffers[1];
585         SecBuffer               InBuffers[1];
586         HANDLE                  token;
587         TOKEN_USER              *tokenuser;
588         DWORD                   retlen;
589         char                    accountname[MAXPGPATH];
590         char                    domainname[MAXPGPATH];
591         DWORD                   accountnamesize = sizeof(accountname);
592         DWORD                   domainnamesize = sizeof(domainname);
593         SID_NAME_USE    accountnameuse;
594
595
596         /*
597          * Acquire a handle to the server credentials.
598          */
599         r = AcquireCredentialsHandle(NULL,
600                 "negotiate",
601                 SECPKG_CRED_INBOUND,
602                 NULL,
603                 NULL,
604                 NULL,
605                 NULL,
606                 &sspicred,
607                 &expiry);
608         if (r != SEC_E_OK)
609                 pg_SSPI_error(ERROR, 
610                                         gettext_noop("could not acquire SSPI credentials handle"), r);
611
612         /*
613          * Loop through SSPI message exchange. This exchange can consist
614          * of multiple messags sent in both directions. First message is always
615          * from the client. All messages from client to server are password
616          * packets (type 'p').
617          */
618         do 
619         {
620                 mtype = pq_getbyte();
621                 if (mtype != 'p')
622                 {
623                         /* Only log error if client didn't disconnect. */
624                         if (mtype != EOF)
625                                 ereport(COMMERROR,
626                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
627                                                  errmsg("expected SSPI response, got message type %d",
628                                                          mtype)));
629                         return STATUS_ERROR;
630                 }
631
632                 /* Get the actual SSPI token */
633                 initStringInfo(&buf);
634                 if (pq_getmessage(&buf, 2000))
635                 {
636                         /* EOF - pq_getmessage already logged error */
637                         pfree(buf.data);
638                         return STATUS_ERROR;
639                 }
640
641                 /* Map to SSPI style buffer */
642                 inbuf.ulVersion = SECBUFFER_VERSION;
643                 inbuf.cBuffers = 1;
644                 inbuf.pBuffers = InBuffers;
645                 InBuffers[0].pvBuffer = buf.data;
646                 InBuffers[0].cbBuffer = buf.len;
647                 InBuffers[0].BufferType = SECBUFFER_TOKEN;
648
649                 /* Prepare output buffer */
650                 OutBuffers[0].pvBuffer = NULL;
651                 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
652                 OutBuffers[0].cbBuffer = 0;
653                 outbuf.cBuffers = 1;
654                 outbuf.pBuffers = OutBuffers;
655                 outbuf.ulVersion = SECBUFFER_VERSION;
656
657
658                 elog(DEBUG4, "Processing received SSPI token of length %u", 
659                          (unsigned int) buf.len);
660
661                 r = AcceptSecurityContext(&sspicred,
662                         sspictx,
663                         &inbuf,
664                         ASC_REQ_ALLOCATE_MEMORY,
665                         SECURITY_NETWORK_DREP,
666                         &newctx,
667                         &outbuf,
668                         &contextattr,
669                         NULL);
670
671                 /* input buffer no longer used */
672                 pfree(buf.data);
673
674                 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
675                 {
676                         /*
677                          * Negotiation generated data to be sent to the client.
678                          */
679                         elog(DEBUG4, "sending SSPI response token of length %u",
680                                  (unsigned int) outbuf.pBuffers[0].cbBuffer);
681
682                         port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
683                         port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
684
685                         sendAuthRequest(port, AUTH_REQ_GSS_CONT);
686
687                         FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
688                 }
689
690                 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
691                 {
692                         if (sspictx != NULL)
693                         {
694                                 DeleteSecurityContext(sspictx);
695                                 free(sspictx);
696                         }
697                         FreeCredentialsHandle(&sspicred);
698                         pg_SSPI_error(ERROR, 
699                                         gettext_noop("could not accept SSPI security context"), r);
700                 }
701
702                 if (sspictx == NULL)
703                 {
704                         sspictx = malloc(sizeof(CtxtHandle));
705                         if (sspictx == NULL)
706                                 ereport(ERROR,
707                                         (errmsg("out of memory")));
708
709                         memcpy(sspictx, &newctx, sizeof(CtxtHandle));
710                 }
711
712                 if (r == SEC_I_CONTINUE_NEEDED)
713                         elog(DEBUG4, "SSPI continue needed");
714
715         } while (r == SEC_I_CONTINUE_NEEDED);
716
717
718         /*
719          * Release service principal credentials
720          */
721         FreeCredentialsHandle(&sspicred);
722
723
724         /*
725          * SEC_E_OK indicates that authentication is now complete.
726          *
727          * Get the name of the user that authenticated, and compare it to the
728          * pg username that was specified for the connection.
729          */
730
731         r = QuerySecurityContextToken(sspictx, &token);
732         if (r != SEC_E_OK)
733                 pg_SSPI_error(ERROR,
734                         gettext_noop("could not get security token from context"), r);
735
736         /*
737          * No longer need the security context, everything from here on uses the
738          * token instead.
739          */
740         DeleteSecurityContext(sspictx);
741         free(sspictx);
742
743         if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
744                 ereport(ERROR,
745                                 (errmsg_internal("could not get token user size: error code %d",
746                                         (int) GetLastError())));
747
748         tokenuser = malloc(retlen);
749         if (tokenuser == NULL)
750                 ereport(ERROR,
751                                 (errmsg("out of memory")));
752
753         if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
754                 ereport(ERROR,
755                                 (errmsg_internal("could not get user token: error code %d",
756                                         (int) GetLastError())));
757
758         if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize, 
759                                                         domainname, &domainnamesize, &accountnameuse))
760                 ereport(ERROR,
761                                 (errmsg_internal("could not lookup acconut sid: error code %d",
762                                         (int) GetLastError())));
763
764         free(tokenuser);
765
766         /*
767          * We have the username (without domain/realm) in accountname, compare 
768          * to the supplied value. In SSPI, always compare case insensitive.
769          */
770         if (pg_strcasecmp(port->user_name, accountname))
771         {
772                 /* GSS name and PGUSER are not equivalent */
773                 elog(DEBUG2, 
774                          "provided username (%s) and SSPI username (%s) don't match",
775                          port->user_name, accountname);
776
777                 return STATUS_ERROR;
778         }
779         
780         return STATUS_OK;
781 }
782 #else   /* no ENABLE_SSPI */
783 static int
784 pg_SSPI_recvauth(Port *port)
785 {
786         ereport(LOG,
787                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
788                          errmsg("SSPI not implemented on this server.")));
789         return STATUS_ERROR;
790 }
791 #endif  /* ENABLE_SSPI */
792
793
794 /*
795  * Tell the user the authentication failed, but not (much about) why.
796  *
797  * There is a tradeoff here between security concerns and making life
798  * unnecessarily difficult for legitimate users.  We would not, for example,
799  * want to report the password we were expecting to receive...
800  * But it seems useful to report the username and authorization method
801  * in use, and these are items that must be presumed known to an attacker
802  * anyway.
803  * Note that many sorts of failure report additional information in the
804  * postmaster log, which we hope is only readable by good guys.
805  */
806 static void
807 auth_failed(Port *port, int status)
808 {
809         const char *errstr;
810
811         /*
812          * If we failed due to EOF from client, just quit; there's no point in
813          * trying to send a message to the client, and not much point in logging
814          * the failure in the postmaster log.  (Logging the failure might be
815          * desirable, were it not for the fact that libpq closes the connection
816          * unceremoniously if challenged for a password when it hasn't got one to
817          * send.  We'll get a useless log entry for every psql connection under
818          * password auth, even if it's perfectly successful, if we log STATUS_EOF
819          * events.)
820          */
821         if (status == STATUS_EOF)
822                 proc_exit(0);
823
824         switch (port->auth_method)
825         {
826                 case uaReject:
827                         errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
828                         break;
829                 case uaKrb5:
830                         errstr = gettext_noop("Kerberos 5 authentication failed for user \"%s\"");
831                         break;
832                 case uaGSS:
833                         errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
834                         break;
835                 case uaSSPI:
836                         errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
837                         break;
838                 case uaTrust:
839                         errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
840                         break;
841                 case uaIdent:
842                         errstr = gettext_noop("Ident authentication failed for user \"%s\"");
843                         break;
844                 case uaMD5:
845                 case uaCrypt:
846                 case uaPassword:
847                         errstr = gettext_noop("password authentication failed for user \"%s\"");
848                         break;
849 #ifdef USE_PAM
850                 case uaPAM:
851                         errstr = gettext_noop("PAM authentication failed for user \"%s\"");
852                         break;
853 #endif   /* USE_PAM */
854 #ifdef USE_LDAP
855                 case uaLDAP:
856                         errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
857                         break;
858 #endif   /* USE_LDAP */
859                 default:
860                         errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
861                         break;
862         }
863
864         ereport(FATAL,
865                         (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
866                          errmsg(errstr, port->user_name)));
867         /* doesn't return */
868 }
869
870
871 /*
872  * Client authentication starts here.  If there is an error, this
873  * function does not return and the backend process is terminated.
874  */
875 void
876 ClientAuthentication(Port *port)
877 {
878         int                     status = STATUS_ERROR;
879
880         /*
881          * Get the authentication method to use for this frontend/database
882          * combination.  Note: a failure return indicates a problem with the hba
883          * config file, not with the request.  hba.c should have dropped an error
884          * message into the postmaster logfile if it failed.
885          */
886         if (hba_getauthmethod(port) != STATUS_OK)
887                 ereport(FATAL,
888                                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
889                                  errmsg("missing or erroneous pg_hba.conf file"),
890                                  errhint("See server log for details.")));
891
892         switch (port->auth_method)
893         {
894                 case uaReject:
895
896                         /*
897                          * This could have come from an explicit "reject" entry in
898                          * pg_hba.conf, but more likely it means there was no matching
899                          * entry.  Take pity on the poor user and issue a helpful error
900                          * message.  NOTE: this is not a security breach, because all the
901                          * info reported here is known at the frontend and must be assumed
902                          * known to bad guys. We're merely helping out the less clueful
903                          * good guys.
904                          */
905                         {
906                                 char            hostinfo[NI_MAXHOST];
907
908                                 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
909                                                                    hostinfo, sizeof(hostinfo),
910                                                                    NULL, 0,
911                                                                    NI_NUMERICHOST);
912
913 #ifdef USE_SSL
914                                 ereport(FATAL,
915                                                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
916                                                  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
917                                                           hostinfo, port->user_name, port->database_name,
918                                                                 port->ssl ? _("SSL on") : _("SSL off"))));
919 #else
920                                 ereport(FATAL,
921                                                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
922                                                  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
923                                                    hostinfo, port->user_name, port->database_name)));
924 #endif
925                                 break;
926                         }
927
928                 case uaKrb5:
929                         sendAuthRequest(port, AUTH_REQ_KRB5);
930                         status = pg_krb5_recvauth(port);
931                         break;
932
933                 case uaGSS:
934                         sendAuthRequest(port, AUTH_REQ_GSS);
935                         status = pg_GSS_recvauth(port);
936                         break;
937
938                 case uaSSPI:
939                         sendAuthRequest(port, AUTH_REQ_SSPI);
940                         status = pg_SSPI_recvauth(port);
941                         break;
942
943                 case uaIdent:
944
945                         /*
946                          * If we are doing ident on unix-domain sockets, use SCM_CREDS
947                          * only if it is defined and SO_PEERCRED isn't.
948                          */
949 #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \
950         (defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
951          (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)))
952                         if (port->raddr.addr.ss_family == AF_UNIX)
953                         {
954 #if defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
955
956                                 /*
957                                  * Receive credentials on next message receipt, BSD/OS,
958                                  * NetBSD. We need to set this before the client sends the
959                                  * next packet.
960                                  */
961                                 int                     on = 1;
962
963                                 if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0)
964                                         ereport(FATAL,
965                                                         (errcode_for_socket_access(),
966                                            errmsg("could not enable credential reception: %m")));
967 #endif
968
969                                 sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
970                         }
971 #endif
972                         status = authident(port);
973                         break;
974
975                 case uaMD5:
976                         sendAuthRequest(port, AUTH_REQ_MD5);
977                         status = recv_and_check_password_packet(port);
978                         break;
979
980                 case uaCrypt:
981                         sendAuthRequest(port, AUTH_REQ_CRYPT);
982                         status = recv_and_check_password_packet(port);
983                         break;
984
985                 case uaPassword:
986                         sendAuthRequest(port, AUTH_REQ_PASSWORD);
987                         status = recv_and_check_password_packet(port);
988                         break;
989
990 #ifdef USE_PAM
991                 case uaPAM:
992                         pam_port_cludge = port;
993                         status = CheckPAMAuth(port, port->user_name, "");
994                         break;
995 #endif   /* USE_PAM */
996
997 #ifdef USE_LDAP
998                 case uaLDAP:
999                         status = CheckLDAPAuth(port);
1000                         break;
1001 #endif
1002
1003                 case uaTrust:
1004                         status = STATUS_OK;
1005                         break;
1006         }
1007
1008         if (status == STATUS_OK)
1009                 sendAuthRequest(port, AUTH_REQ_OK);
1010         else
1011                 auth_failed(port, status);
1012 }
1013
1014
1015 /*
1016  * Send an authentication request packet to the frontend.
1017  */
1018 static void
1019 sendAuthRequest(Port *port, AuthRequest areq)
1020 {
1021         StringInfoData buf;
1022
1023         pq_beginmessage(&buf, 'R');
1024         pq_sendint(&buf, (int32) areq, sizeof(int32));
1025
1026         /* Add the salt for encrypted passwords. */
1027         if (areq == AUTH_REQ_MD5)
1028                 pq_sendbytes(&buf, port->md5Salt, 4);
1029         else if (areq == AUTH_REQ_CRYPT)
1030                 pq_sendbytes(&buf, port->cryptSalt, 2);
1031
1032 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
1033         /* Add the authentication data for the next step of
1034          * the GSSAPI or SSPI negotiation. */
1035         else if (areq == AUTH_REQ_GSS_CONT)
1036         {
1037                 if (port->gss->outbuf.length > 0)
1038                 {
1039                         elog(DEBUG4, "sending GSS token of length %u",
1040                                  (unsigned int) port->gss->outbuf.length);
1041
1042                         pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
1043                 }
1044         }
1045 #endif
1046
1047         pq_endmessage(&buf);
1048
1049         /*
1050          * Flush message so client will see it, except for AUTH_REQ_OK, which need
1051          * not be sent until we are ready for queries.
1052          */
1053         if (areq != AUTH_REQ_OK)
1054                 pq_flush();
1055 }
1056
1057
1058 #ifdef USE_PAM
1059
1060 /*
1061  * PAM conversation function
1062  */
1063
1064 static int
1065 pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
1066                                          struct pam_response ** resp, void *appdata_ptr)
1067 {
1068         if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
1069         {
1070                 switch (msg[0]->msg_style)
1071                 {
1072                         case PAM_ERROR_MSG:
1073                                 ereport(LOG,
1074                                                 (errmsg("error from underlying PAM layer: %s",
1075                                                                 msg[0]->msg)));
1076                                 return PAM_CONV_ERR;
1077                         default:
1078                                 ereport(LOG,
1079                                                 (errmsg("unsupported PAM conversation %d/%s",
1080                                                                 msg[0]->msg_style, msg[0]->msg)));
1081                                 return PAM_CONV_ERR;
1082                 }
1083         }
1084
1085         if (!appdata_ptr)
1086         {
1087                 /*
1088                  * Workaround for Solaris 2.6 where the PAM library is broken and does
1089                  * not pass appdata_ptr to the conversation routine
1090                  */
1091                 appdata_ptr = pam_passwd;
1092         }
1093
1094         /*
1095          * Password wasn't passed to PAM the first time around - let's go ask the
1096          * client to send a password, which we then stuff into PAM.
1097          */
1098         if (strlen(appdata_ptr) == 0)
1099         {
1100                 char       *passwd;
1101
1102                 sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);
1103                 passwd = recv_password_packet(pam_port_cludge);
1104
1105                 if (passwd == NULL)
1106                         return PAM_CONV_ERR;    /* client didn't want to send password */
1107
1108                 if (strlen(passwd) == 0)
1109                 {
1110                         ereport(LOG,
1111                                         (errmsg("empty password returned by client")));
1112                         return PAM_CONV_ERR;
1113                 }
1114                 appdata_ptr = passwd;
1115         }
1116
1117         /*
1118          * Explicitly not using palloc here - PAM will free this memory in
1119          * pam_end()
1120          */
1121         *resp = calloc(num_msg, sizeof(struct pam_response));
1122         if (!*resp)
1123         {
1124                 ereport(LOG,
1125                                 (errcode(ERRCODE_OUT_OF_MEMORY),
1126                                  errmsg("out of memory")));
1127                 return PAM_CONV_ERR;
1128         }
1129
1130         (*resp)[0].resp = strdup((char *) appdata_ptr);
1131         (*resp)[0].resp_retcode = 0;
1132
1133         return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
1134 }
1135
1136
1137 /*
1138  * Check authentication against PAM.
1139  */
1140 static int
1141 CheckPAMAuth(Port *port, char *user, char *password)
1142 {
1143         int                     retval;
1144         pam_handle_t *pamh = NULL;
1145
1146         /*
1147          * Apparently, Solaris 2.6 is broken, and needs ugly static variable
1148          * workaround
1149          */
1150         pam_passwd = password;
1151
1152         /*
1153          * Set the application data portion of the conversation struct This is
1154          * later used inside the PAM conversation to pass the password to the
1155          * authentication module.
1156          */
1157         pam_passw_conv.appdata_ptr = (char *) password;         /* from password above,
1158                                                                                                                  * not allocated */
1159
1160         /* Optionally, one can set the service name in pg_hba.conf */
1161         if (port->auth_arg && port->auth_arg[0] != '\0')
1162                 retval = pam_start(port->auth_arg, "pgsql@",
1163                                                    &pam_passw_conv, &pamh);
1164         else
1165                 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
1166                                                    &pam_passw_conv, &pamh);
1167
1168         if (retval != PAM_SUCCESS)
1169         {
1170                 ereport(LOG,
1171                                 (errmsg("could not create PAM authenticator: %s",
1172                                                 pam_strerror(pamh, retval))));
1173                 pam_passwd = NULL;              /* Unset pam_passwd */
1174                 return STATUS_ERROR;
1175         }
1176
1177         retval = pam_set_item(pamh, PAM_USER, user);
1178
1179         if (retval != PAM_SUCCESS)
1180         {
1181                 ereport(LOG,
1182                                 (errmsg("pam_set_item(PAM_USER) failed: %s",
1183                                                 pam_strerror(pamh, retval))));
1184                 pam_passwd = NULL;              /* Unset pam_passwd */
1185                 return STATUS_ERROR;
1186         }
1187
1188         retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
1189
1190         if (retval != PAM_SUCCESS)
1191         {
1192                 ereport(LOG,
1193                                 (errmsg("pam_set_item(PAM_CONV) failed: %s",
1194                                                 pam_strerror(pamh, retval))));
1195                 pam_passwd = NULL;              /* Unset pam_passwd */
1196                 return STATUS_ERROR;
1197         }
1198
1199         retval = pam_authenticate(pamh, 0);
1200
1201         if (retval != PAM_SUCCESS)
1202         {
1203                 ereport(LOG,
1204                                 (errmsg("pam_authenticate failed: %s",
1205                                                 pam_strerror(pamh, retval))));
1206                 pam_passwd = NULL;              /* Unset pam_passwd */
1207                 return STATUS_ERROR;
1208         }
1209
1210         retval = pam_acct_mgmt(pamh, 0);
1211
1212         if (retval != PAM_SUCCESS)
1213         {
1214                 ereport(LOG,
1215                                 (errmsg("pam_acct_mgmt failed: %s",
1216                                                 pam_strerror(pamh, retval))));
1217                 pam_passwd = NULL;              /* Unset pam_passwd */
1218                 return STATUS_ERROR;
1219         }
1220
1221         retval = pam_end(pamh, retval);
1222
1223         if (retval != PAM_SUCCESS)
1224         {
1225                 ereport(LOG,
1226                                 (errmsg("could not release PAM authenticator: %s",
1227                                                 pam_strerror(pamh, retval))));
1228         }
1229
1230         pam_passwd = NULL;                      /* Unset pam_passwd */
1231
1232         return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
1233 }
1234 #endif   /* USE_PAM */
1235
1236
1237 #ifdef USE_LDAP
1238
1239 static int
1240 CheckLDAPAuth(Port *port)
1241 {
1242         char       *passwd;
1243         char            server[128];
1244         char            basedn[128];
1245         char            prefix[128];
1246         char            suffix[128];
1247         LDAP       *ldap;
1248         bool            ssl = false;
1249         int                     r;
1250         int                     ldapversion = LDAP_VERSION3;
1251         int                     ldapport = LDAP_PORT;
1252         char            fulluser[NAMEDATALEN + 256 + 1];
1253
1254         if (!port->auth_arg || port->auth_arg[0] == '\0')
1255         {
1256                 ereport(LOG,
1257                                 (errmsg("LDAP configuration URL not specified")));
1258                 return STATUS_ERROR;
1259         }
1260
1261         /*
1262          * Crack the LDAP url. We do a very trivial parse..
1263          * ldap[s]://<server>[:<port>]/<basedn>[;prefix[;suffix]]
1264          */
1265
1266         server[0] = '\0';
1267         basedn[0] = '\0';
1268         prefix[0] = '\0';
1269         suffix[0] = '\0';
1270
1271         /* ldap, including port number */
1272         r = sscanf(port->auth_arg,
1273                            "ldap://%127[^:]:%d/%127[^;];%127[^;];%127s",
1274                            server, &ldapport, basedn, prefix, suffix);
1275         if (r < 3)
1276         {
1277                 /* ldaps, including port number */
1278                 r = sscanf(port->auth_arg,
1279                                    "ldaps://%127[^:]:%d/%127[^;];%127[^;];%127s",
1280                                    server, &ldapport, basedn, prefix, suffix);
1281                 if (r >= 3)
1282                         ssl = true;
1283         }
1284         if (r < 3)
1285         {
1286                 /* ldap, no port number */
1287                 r = sscanf(port->auth_arg,
1288                                    "ldap://%127[^/]/%127[^;];%127[^;];%127s",
1289                                    server, basedn, prefix, suffix);
1290         }
1291         if (r < 2)
1292         {
1293                 /* ldaps, no port number */
1294                 r = sscanf(port->auth_arg,
1295                                    "ldaps://%127[^/]/%127[^;];%127[^;];%127s",
1296                                    server, basedn, prefix, suffix);
1297                 if (r >= 2)
1298                         ssl = true;
1299         }
1300         if (r < 2)
1301         {
1302                 ereport(LOG,
1303                                 (errmsg("invalid LDAP URL: \"%s\"",
1304                                                 port->auth_arg)));
1305                 return STATUS_ERROR;
1306         }
1307
1308         sendAuthRequest(port, AUTH_REQ_PASSWORD);
1309
1310         passwd = recv_password_packet(port);
1311         if (passwd == NULL)
1312                 return STATUS_EOF;              /* client wouldn't send password */
1313
1314         ldap = ldap_init(server, ldapport);
1315         if (!ldap)
1316         {
1317 #ifndef WIN32
1318                 ereport(LOG,
1319                                 (errmsg("could not initialize LDAP: error code %d",
1320                                                 errno)));
1321 #else
1322                 ereport(LOG,
1323                                 (errmsg("could not initialize LDAP: error code %d",
1324                                                 (int) LdapGetLastError())));
1325 #endif
1326                 return STATUS_ERROR;
1327         }
1328
1329         if ((r = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
1330         {
1331                 ldap_unbind(ldap);
1332                 ereport(LOG,
1333                                 (errmsg("could not set LDAP protocol version: error code %d", r)));
1334                 return STATUS_ERROR;
1335         }
1336
1337         if (ssl)
1338         {
1339 #ifndef WIN32
1340                 if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
1341 #else
1342                 static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
1343
1344                 if (_ldap_start_tls_sA == NULL)
1345                 {
1346                         /*
1347                          * Need to load this function dynamically because it does not
1348                          * exist on Windows 2000, and causes a load error for the whole
1349                          * exe if referenced.
1350                          */
1351                         HANDLE          ldaphandle;
1352
1353                         ldaphandle = LoadLibrary("WLDAP32.DLL");
1354                         if (ldaphandle == NULL)
1355                         {
1356                                 /*
1357                                  * should never happen since we import other files from
1358                                  * wldap32, but check anyway
1359                                  */
1360                                 ldap_unbind(ldap);
1361                                 ereport(LOG,
1362                                                 (errmsg("could not load wldap32.dll")));
1363                                 return STATUS_ERROR;
1364                         }
1365                         _ldap_start_tls_sA = (__ldap_start_tls_sA) GetProcAddress(ldaphandle, "ldap_start_tls_sA");
1366                         if (_ldap_start_tls_sA == NULL)
1367                         {
1368                                 ldap_unbind(ldap);
1369                                 ereport(LOG,
1370                                                 (errmsg("could not load function _ldap_start_tls_sA in wldap32.dll"),
1371                                                  errdetail("LDAP over SSL is not supported on this platform.")));
1372                                 return STATUS_ERROR;
1373                         }
1374
1375                         /*
1376                          * Leak LDAP handle on purpose, because we need the library to stay
1377                          * open. This is ok because it will only ever be leaked once per
1378                          * process and is automatically cleaned up on process exit.
1379                          */
1380                 }
1381                 if ((r = _ldap_start_tls_sA(ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
1382 #endif
1383                 {
1384                         ldap_unbind(ldap);
1385                         ereport(LOG,
1386                                         (errmsg("could not start LDAP TLS session: error code %d", r)));
1387                         return STATUS_ERROR;
1388                 }
1389         }
1390
1391         snprintf(fulluser, sizeof(fulluser), "%s%s%s",
1392                          prefix, port->user_name, suffix);
1393         fulluser[sizeof(fulluser) - 1] = '\0';
1394
1395         r = ldap_simple_bind_s(ldap, fulluser, passwd);
1396         ldap_unbind(ldap);
1397
1398         if (r != LDAP_SUCCESS)
1399         {
1400                 ereport(LOG,
1401                                 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
1402                                                 fulluser, server, r)));
1403                 return STATUS_ERROR;
1404         }
1405
1406         return STATUS_OK;
1407 }
1408 #endif   /* USE_LDAP */
1409
1410 /*
1411  * Collect password response packet from frontend.
1412  *
1413  * Returns NULL if couldn't get password, else palloc'd string.
1414  */
1415 static char *
1416 recv_password_packet(Port *port)
1417 {
1418         StringInfoData buf;
1419
1420         if (PG_PROTOCOL_MAJOR(port->proto) >= 3)
1421         {
1422                 /* Expect 'p' message type */
1423                 int                     mtype;
1424
1425                 mtype = pq_getbyte();
1426                 if (mtype != 'p')
1427                 {
1428                         /*
1429                          * If the client just disconnects without offering a password,
1430                          * don't make a log entry.  This is legal per protocol spec and in
1431                          * fact commonly done by psql, so complaining just clutters the
1432                          * log.
1433                          */
1434                         if (mtype != EOF)
1435                                 ereport(COMMERROR,
1436                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1437                                         errmsg("expected password response, got message type %d",
1438                                                    mtype)));
1439                         return NULL;            /* EOF or bad message type */
1440                 }
1441         }
1442         else
1443         {
1444                 /* For pre-3.0 clients, avoid log entry if they just disconnect */
1445                 if (pq_peekbyte() == EOF)
1446                         return NULL;            /* EOF */
1447         }
1448
1449         initStringInfo(&buf);
1450         if (pq_getmessage(&buf, 1000))          /* receive password */
1451         {
1452                 /* EOF - pq_getmessage already logged a suitable message */
1453                 pfree(buf.data);
1454                 return NULL;
1455         }
1456
1457         /*
1458          * Apply sanity check: password packet length should agree with length of
1459          * contained string.  Note it is safe to use strlen here because
1460          * StringInfo is guaranteed to have an appended '\0'.
1461          */
1462         if (strlen(buf.data) + 1 != buf.len)
1463                 ereport(COMMERROR,
1464                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1465                                  errmsg("invalid password packet size")));
1466
1467         /* Do not echo password to logs, for security. */
1468         ereport(DEBUG5,
1469                         (errmsg("received password packet")));
1470
1471         /*
1472          * Return the received string.  Note we do not attempt to do any
1473          * character-set conversion on it; since we don't yet know the client's
1474          * encoding, there wouldn't be much point.
1475          */
1476         return buf.data;
1477 }
1478
1479
1480 /*
1481  * Called when we have sent an authorization request for a password.
1482  * Get the response and check it.
1483  */
1484 static int
1485 recv_and_check_password_packet(Port *port)
1486 {
1487         char       *passwd;
1488         int                     result;
1489
1490         passwd = recv_password_packet(port);
1491
1492         if (passwd == NULL)
1493                 return STATUS_EOF;              /* client wouldn't send password */
1494
1495         result = md5_crypt_verify(port, port->user_name, passwd);
1496
1497         pfree(passwd);
1498
1499         return result;
1500 }