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