]> granicus.if.org Git - postgresql/blob - src/backend/libpq/auth.c
Enable GSSAPI to build using MSVC. Always build GSSAPI when Kerberos is
[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.152 2007/07/12 14:43:20 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                          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: %i, "
458                                          "minor: %i, outlen: %u, outflags: %x",
459                                          maj_stat, min_stat,
460                                          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                         elog(DEBUG4, "sending GSS response token of length %u",
468                                  port->gss->outbuf.length);
469
470                         sendAuthRequest(port, AUTH_REQ_GSS_CONT);
471                 }
472
473                 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
474                 {
475                         OM_uint32       lmin_s;
476                         gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
477                         pg_GSS_error(ERROR, 
478                                         gettext_noop("accepting GSS security context failed"),
479                                         maj_stat, min_stat);
480                 }
481
482                 if (maj_stat == GSS_S_CONTINUE_NEEDED)
483                         elog(DEBUG4, "GSS continue needed");
484
485         } while (maj_stat == GSS_S_CONTINUE_NEEDED);
486
487         if (port->gss->cred != GSS_C_NO_CREDENTIAL)
488         {
489                 /*
490                  * Release service principal credentials
491                  */
492                 gss_release_cred(&min_stat, port->gss->cred);
493         }
494
495         /*
496          * GSS_S_COMPLETE indicates that authentication is now complete.
497          *
498          * Get the name of the user that authenticated, and compare it to the
499          * pg username that was specified for the connection.
500          */
501         maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
502         if (maj_stat != GSS_S_COMPLETE)
503                 pg_GSS_error(ERROR,
504                                          gettext_noop("retreiving GSS user name failed"),
505                                          maj_stat, min_stat);
506
507         /*
508          * Compare the part of the username that comes before the @
509          * sign only (ignore realm). The GSSAPI libraries won't have 
510          * authenticated the user if he's from an invalid realm.
511          */
512         if (strchr(gbuf.value, '@'))
513         {
514                 char *cp = strchr(gbuf.value, '@');
515                 *cp = '\0';
516         }
517
518         if (pg_krb_caseins_users)
519                 ret = pg_strcasecmp(port->user_name, gbuf.value);
520         else
521                 ret = strcmp(port->user_name, gbuf.value);
522
523         if (ret)
524         {
525                 /* GSS name and PGUSER are not equivalent */
526                 elog(DEBUG2, 
527                          "provided username (%s) and GSSAPI username (%s) don't match",
528                          port->user_name, (char *)gbuf.value);
529
530                 gss_release_buffer(&lmin_s, &gbuf);
531                 return STATUS_ERROR;
532         }
533         
534         gss_release_buffer(&lmin_s, &gbuf);
535
536         return STATUS_OK;
537 }
538
539 #else   /* no ENABLE_GSS */
540 static int
541 pg_GSS_recvauth(Port *port)
542 {
543         ereport(LOG,
544                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
545                          errmsg("GSSAPI not implemented on this server.")));
546         return STATUS_ERROR;
547 }
548 #endif  /* ENABLE_GSS */
549
550
551 /*
552  * Tell the user the authentication failed, but not (much about) why.
553  *
554  * There is a tradeoff here between security concerns and making life
555  * unnecessarily difficult for legitimate users.  We would not, for example,
556  * want to report the password we were expecting to receive...
557  * But it seems useful to report the username and authorization method
558  * in use, and these are items that must be presumed known to an attacker
559  * anyway.
560  * Note that many sorts of failure report additional information in the
561  * postmaster log, which we hope is only readable by good guys.
562  */
563 static void
564 auth_failed(Port *port, int status)
565 {
566         const char *errstr;
567
568         /*
569          * If we failed due to EOF from client, just quit; there's no point in
570          * trying to send a message to the client, and not much point in logging
571          * the failure in the postmaster log.  (Logging the failure might be
572          * desirable, were it not for the fact that libpq closes the connection
573          * unceremoniously if challenged for a password when it hasn't got one to
574          * send.  We'll get a useless log entry for every psql connection under
575          * password auth, even if it's perfectly successful, if we log STATUS_EOF
576          * events.)
577          */
578         if (status == STATUS_EOF)
579                 proc_exit(0);
580
581         switch (port->auth_method)
582         {
583                 case uaReject:
584                         errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
585                         break;
586                 case uaKrb5:
587                         errstr = gettext_noop("Kerberos 5 authentication failed for user \"%s\"");
588                         break;
589                 case uaGSS:
590                         errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
591                         break;
592                 case uaTrust:
593                         errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
594                         break;
595                 case uaIdent:
596                         errstr = gettext_noop("Ident authentication failed for user \"%s\"");
597                         break;
598                 case uaMD5:
599                 case uaCrypt:
600                 case uaPassword:
601                         errstr = gettext_noop("password authentication failed for user \"%s\"");
602                         break;
603 #ifdef USE_PAM
604                 case uaPAM:
605                         errstr = gettext_noop("PAM authentication failed for user \"%s\"");
606                         break;
607 #endif   /* USE_PAM */
608 #ifdef USE_LDAP
609                 case uaLDAP:
610                         errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
611                         break;
612 #endif   /* USE_LDAP */
613                 default:
614                         errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
615                         break;
616         }
617
618         ereport(FATAL,
619                         (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
620                          errmsg(errstr, port->user_name)));
621         /* doesn't return */
622 }
623
624
625 /*
626  * Client authentication starts here.  If there is an error, this
627  * function does not return and the backend process is terminated.
628  */
629 void
630 ClientAuthentication(Port *port)
631 {
632         int                     status = STATUS_ERROR;
633
634         /*
635          * Get the authentication method to use for this frontend/database
636          * combination.  Note: a failure return indicates a problem with the hba
637          * config file, not with the request.  hba.c should have dropped an error
638          * message into the postmaster logfile if it failed.
639          */
640         if (hba_getauthmethod(port) != STATUS_OK)
641                 ereport(FATAL,
642                                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
643                                  errmsg("missing or erroneous pg_hba.conf file"),
644                                  errhint("See server log for details.")));
645
646         switch (port->auth_method)
647         {
648                 case uaReject:
649
650                         /*
651                          * This could have come from an explicit "reject" entry in
652                          * pg_hba.conf, but more likely it means there was no matching
653                          * entry.  Take pity on the poor user and issue a helpful error
654                          * message.  NOTE: this is not a security breach, because all the
655                          * info reported here is known at the frontend and must be assumed
656                          * known to bad guys. We're merely helping out the less clueful
657                          * good guys.
658                          */
659                         {
660                                 char            hostinfo[NI_MAXHOST];
661
662                                 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
663                                                                    hostinfo, sizeof(hostinfo),
664                                                                    NULL, 0,
665                                                                    NI_NUMERICHOST);
666
667 #ifdef USE_SSL
668                                 ereport(FATAL,
669                                                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
670                                                  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
671                                                           hostinfo, port->user_name, port->database_name,
672                                                                 port->ssl ? _("SSL on") : _("SSL off"))));
673 #else
674                                 ereport(FATAL,
675                                                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
676                                                  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
677                                                    hostinfo, port->user_name, port->database_name)));
678 #endif
679                                 break;
680                         }
681
682                 case uaKrb5:
683                         sendAuthRequest(port, AUTH_REQ_KRB5);
684                         status = pg_krb5_recvauth(port);
685                         break;
686
687                 case uaGSS:
688                         sendAuthRequest(port, AUTH_REQ_GSS);
689                         status = pg_GSS_recvauth(port);
690                         break;
691
692                 case uaIdent:
693
694                         /*
695                          * If we are doing ident on unix-domain sockets, use SCM_CREDS
696                          * only if it is defined and SO_PEERCRED isn't.
697                          */
698 #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \
699         (defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
700          (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)))
701                         if (port->raddr.addr.ss_family == AF_UNIX)
702                         {
703 #if defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
704
705                                 /*
706                                  * Receive credentials on next message receipt, BSD/OS,
707                                  * NetBSD. We need to set this before the client sends the
708                                  * next packet.
709                                  */
710                                 int                     on = 1;
711
712                                 if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0)
713                                         ereport(FATAL,
714                                                         (errcode_for_socket_access(),
715                                            errmsg("could not enable credential reception: %m")));
716 #endif
717
718                                 sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
719                         }
720 #endif
721                         status = authident(port);
722                         break;
723
724                 case uaMD5:
725                         sendAuthRequest(port, AUTH_REQ_MD5);
726                         status = recv_and_check_password_packet(port);
727                         break;
728
729                 case uaCrypt:
730                         sendAuthRequest(port, AUTH_REQ_CRYPT);
731                         status = recv_and_check_password_packet(port);
732                         break;
733
734                 case uaPassword:
735                         sendAuthRequest(port, AUTH_REQ_PASSWORD);
736                         status = recv_and_check_password_packet(port);
737                         break;
738
739 #ifdef USE_PAM
740                 case uaPAM:
741                         pam_port_cludge = port;
742                         status = CheckPAMAuth(port, port->user_name, "");
743                         break;
744 #endif   /* USE_PAM */
745
746 #ifdef USE_LDAP
747                 case uaLDAP:
748                         status = CheckLDAPAuth(port);
749                         break;
750 #endif
751
752                 case uaTrust:
753                         status = STATUS_OK;
754                         break;
755         }
756
757         if (status == STATUS_OK)
758                 sendAuthRequest(port, AUTH_REQ_OK);
759         else
760                 auth_failed(port, status);
761 }
762
763
764 /*
765  * Send an authentication request packet to the frontend.
766  */
767 static void
768 sendAuthRequest(Port *port, AuthRequest areq)
769 {
770         StringInfoData buf;
771
772         pq_beginmessage(&buf, 'R');
773         pq_sendint(&buf, (int32) areq, sizeof(int32));
774
775         /* Add the salt for encrypted passwords. */
776         if (areq == AUTH_REQ_MD5)
777                 pq_sendbytes(&buf, port->md5Salt, 4);
778         else if (areq == AUTH_REQ_CRYPT)
779                 pq_sendbytes(&buf, port->cryptSalt, 2);
780
781 #ifdef ENABLE_GSS
782         /* Add the authentication data for the next step of
783          * the GSSAPI negotiation. */
784         else if (areq == AUTH_REQ_GSS_CONT)
785         {
786                 if (port->gss->outbuf.length > 0)
787                 {
788                         OM_uint32       lmin_s;
789
790                         elog(DEBUG4, "sending GSS token of length %u",
791                                  port->gss->outbuf.length);
792
793                         pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
794                         gss_release_buffer(&lmin_s, &port->gss->outbuf);
795                 }
796         }
797 #endif
798
799         pq_endmessage(&buf);
800
801         /*
802          * Flush message so client will see it, except for AUTH_REQ_OK, which need
803          * not be sent until we are ready for queries.
804          */
805         if (areq != AUTH_REQ_OK)
806                 pq_flush();
807 }
808
809
810 #ifdef USE_PAM
811
812 /*
813  * PAM conversation function
814  */
815
816 static int
817 pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
818                                          struct pam_response ** resp, void *appdata_ptr)
819 {
820         if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
821         {
822                 switch (msg[0]->msg_style)
823                 {
824                         case PAM_ERROR_MSG:
825                                 ereport(LOG,
826                                                 (errmsg("error from underlying PAM layer: %s",
827                                                                 msg[0]->msg)));
828                                 return PAM_CONV_ERR;
829                         default:
830                                 ereport(LOG,
831                                                 (errmsg("unsupported PAM conversation %d/%s",
832                                                                 msg[0]->msg_style, msg[0]->msg)));
833                                 return PAM_CONV_ERR;
834                 }
835         }
836
837         if (!appdata_ptr)
838         {
839                 /*
840                  * Workaround for Solaris 2.6 where the PAM library is broken and does
841                  * not pass appdata_ptr to the conversation routine
842                  */
843                 appdata_ptr = pam_passwd;
844         }
845
846         /*
847          * Password wasn't passed to PAM the first time around - let's go ask the
848          * client to send a password, which we then stuff into PAM.
849          */
850         if (strlen(appdata_ptr) == 0)
851         {
852                 char       *passwd;
853
854                 sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);
855                 passwd = recv_password_packet(pam_port_cludge);
856
857                 if (passwd == NULL)
858                         return PAM_CONV_ERR;    /* client didn't want to send password */
859
860                 if (strlen(passwd) == 0)
861                 {
862                         ereport(LOG,
863                                         (errmsg("empty password returned by client")));
864                         return PAM_CONV_ERR;
865                 }
866                 appdata_ptr = passwd;
867         }
868
869         /*
870          * Explicitly not using palloc here - PAM will free this memory in
871          * pam_end()
872          */
873         *resp = calloc(num_msg, sizeof(struct pam_response));
874         if (!*resp)
875         {
876                 ereport(LOG,
877                                 (errcode(ERRCODE_OUT_OF_MEMORY),
878                                  errmsg("out of memory")));
879                 return PAM_CONV_ERR;
880         }
881
882         (*resp)[0].resp = strdup((char *) appdata_ptr);
883         (*resp)[0].resp_retcode = 0;
884
885         return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
886 }
887
888
889 /*
890  * Check authentication against PAM.
891  */
892 static int
893 CheckPAMAuth(Port *port, char *user, char *password)
894 {
895         int                     retval;
896         pam_handle_t *pamh = NULL;
897
898         /*
899          * Apparently, Solaris 2.6 is broken, and needs ugly static variable
900          * workaround
901          */
902         pam_passwd = password;
903
904         /*
905          * Set the application data portion of the conversation struct This is
906          * later used inside the PAM conversation to pass the password to the
907          * authentication module.
908          */
909         pam_passw_conv.appdata_ptr = (char *) password;         /* from password above,
910                                                                                                                  * not allocated */
911
912         /* Optionally, one can set the service name in pg_hba.conf */
913         if (port->auth_arg && port->auth_arg[0] != '\0')
914                 retval = pam_start(port->auth_arg, "pgsql@",
915                                                    &pam_passw_conv, &pamh);
916         else
917                 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
918                                                    &pam_passw_conv, &pamh);
919
920         if (retval != PAM_SUCCESS)
921         {
922                 ereport(LOG,
923                                 (errmsg("could not create PAM authenticator: %s",
924                                                 pam_strerror(pamh, retval))));
925                 pam_passwd = NULL;              /* Unset pam_passwd */
926                 return STATUS_ERROR;
927         }
928
929         retval = pam_set_item(pamh, PAM_USER, user);
930
931         if (retval != PAM_SUCCESS)
932         {
933                 ereport(LOG,
934                                 (errmsg("pam_set_item(PAM_USER) failed: %s",
935                                                 pam_strerror(pamh, retval))));
936                 pam_passwd = NULL;              /* Unset pam_passwd */
937                 return STATUS_ERROR;
938         }
939
940         retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
941
942         if (retval != PAM_SUCCESS)
943         {
944                 ereport(LOG,
945                                 (errmsg("pam_set_item(PAM_CONV) failed: %s",
946                                                 pam_strerror(pamh, retval))));
947                 pam_passwd = NULL;              /* Unset pam_passwd */
948                 return STATUS_ERROR;
949         }
950
951         retval = pam_authenticate(pamh, 0);
952
953         if (retval != PAM_SUCCESS)
954         {
955                 ereport(LOG,
956                                 (errmsg("pam_authenticate failed: %s",
957                                                 pam_strerror(pamh, retval))));
958                 pam_passwd = NULL;              /* Unset pam_passwd */
959                 return STATUS_ERROR;
960         }
961
962         retval = pam_acct_mgmt(pamh, 0);
963
964         if (retval != PAM_SUCCESS)
965         {
966                 ereport(LOG,
967                                 (errmsg("pam_acct_mgmt failed: %s",
968                                                 pam_strerror(pamh, retval))));
969                 pam_passwd = NULL;              /* Unset pam_passwd */
970                 return STATUS_ERROR;
971         }
972
973         retval = pam_end(pamh, retval);
974
975         if (retval != PAM_SUCCESS)
976         {
977                 ereport(LOG,
978                                 (errmsg("could not release PAM authenticator: %s",
979                                                 pam_strerror(pamh, retval))));
980         }
981
982         pam_passwd = NULL;                      /* Unset pam_passwd */
983
984         return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
985 }
986 #endif   /* USE_PAM */
987
988
989 #ifdef USE_LDAP
990
991 static int
992 CheckLDAPAuth(Port *port)
993 {
994         char       *passwd;
995         char            server[128];
996         char            basedn[128];
997         char            prefix[128];
998         char            suffix[128];
999         LDAP       *ldap;
1000         bool            ssl = false;
1001         int                     r;
1002         int                     ldapversion = LDAP_VERSION3;
1003         int                     ldapport = LDAP_PORT;
1004         char            fulluser[NAMEDATALEN + 256 + 1];
1005
1006         if (!port->auth_arg || port->auth_arg[0] == '\0')
1007         {
1008                 ereport(LOG,
1009                                 (errmsg("LDAP configuration URL not specified")));
1010                 return STATUS_ERROR;
1011         }
1012
1013         /*
1014          * Crack the LDAP url. We do a very trivial parse..
1015          * ldap[s]://<server>[:<port>]/<basedn>[;prefix[;suffix]]
1016          */
1017
1018         server[0] = '\0';
1019         basedn[0] = '\0';
1020         prefix[0] = '\0';
1021         suffix[0] = '\0';
1022
1023         /* ldap, including port number */
1024         r = sscanf(port->auth_arg,
1025                            "ldap://%127[^:]:%i/%127[^;];%127[^;];%127s",
1026                            server, &ldapport, basedn, prefix, suffix);
1027         if (r < 3)
1028         {
1029                 /* ldaps, including port number */
1030                 r = sscanf(port->auth_arg,
1031                                    "ldaps://%127[^:]:%i/%127[^;];%127[^;];%127s",
1032                                    server, &ldapport, basedn, prefix, suffix);
1033                 if (r >= 3)
1034                         ssl = true;
1035         }
1036         if (r < 3)
1037         {
1038                 /* ldap, no port number */
1039                 r = sscanf(port->auth_arg,
1040                                    "ldap://%127[^/]/%127[^;];%127[^;];%127s",
1041                                    server, basedn, prefix, suffix);
1042         }
1043         if (r < 2)
1044         {
1045                 /* ldaps, no port number */
1046                 r = sscanf(port->auth_arg,
1047                                    "ldaps://%127[^/]/%127[^;];%127[^;];%127s",
1048                                    server, basedn, prefix, suffix);
1049                 if (r >= 2)
1050                         ssl = true;
1051         }
1052         if (r < 2)
1053         {
1054                 ereport(LOG,
1055                                 (errmsg("invalid LDAP URL: \"%s\"",
1056                                                 port->auth_arg)));
1057                 return STATUS_ERROR;
1058         }
1059
1060         sendAuthRequest(port, AUTH_REQ_PASSWORD);
1061
1062         passwd = recv_password_packet(port);
1063         if (passwd == NULL)
1064                 return STATUS_EOF;              /* client wouldn't send password */
1065
1066         ldap = ldap_init(server, ldapport);
1067         if (!ldap)
1068         {
1069 #ifndef WIN32
1070                 ereport(LOG,
1071                                 (errmsg("could not initialize LDAP: error code %d",
1072                                                 errno)));
1073 #else
1074                 ereport(LOG,
1075                                 (errmsg("could not initialize LDAP: error code %d",
1076                                                 (int) LdapGetLastError())));
1077 #endif
1078                 return STATUS_ERROR;
1079         }
1080
1081         if ((r = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
1082         {
1083                 ldap_unbind(ldap);
1084                 ereport(LOG,
1085                                 (errmsg("could not set LDAP protocol version: error code %d", r)));
1086                 return STATUS_ERROR;
1087         }
1088
1089         if (ssl)
1090         {
1091 #ifndef WIN32
1092                 if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
1093 #else
1094                 static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
1095
1096                 if (_ldap_start_tls_sA == NULL)
1097                 {
1098                         /*
1099                          * Need to load this function dynamically because it does not
1100                          * exist on Windows 2000, and causes a load error for the whole
1101                          * exe if referenced.
1102                          */
1103                         HANDLE          ldaphandle;
1104
1105                         ldaphandle = LoadLibrary("WLDAP32.DLL");
1106                         if (ldaphandle == NULL)
1107                         {
1108                                 /*
1109                                  * should never happen since we import other files from
1110                                  * wldap32, but check anyway
1111                                  */
1112                                 ldap_unbind(ldap);
1113                                 ereport(LOG,
1114                                                 (errmsg("could not load wldap32.dll")));
1115                                 return STATUS_ERROR;
1116                         }
1117                         _ldap_start_tls_sA = (__ldap_start_tls_sA) GetProcAddress(ldaphandle, "ldap_start_tls_sA");
1118                         if (_ldap_start_tls_sA == NULL)
1119                         {
1120                                 ldap_unbind(ldap);
1121                                 ereport(LOG,
1122                                                 (errmsg("could not load function _ldap_start_tls_sA in wldap32.dll"),
1123                                                  errdetail("LDAP over SSL is not supported on this platform.")));
1124                                 return STATUS_ERROR;
1125                         }
1126
1127                         /*
1128                          * Leak LDAP handle on purpose, because we need the library to stay
1129                          * open. This is ok because it will only ever be leaked once per
1130                          * process and is automatically cleaned up on process exit.
1131                          */
1132                 }
1133                 if ((r = _ldap_start_tls_sA(ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
1134 #endif
1135                 {
1136                         ldap_unbind(ldap);
1137                         ereport(LOG,
1138                                         (errmsg("could not start LDAP TLS session: error code %d", r)));
1139                         return STATUS_ERROR;
1140                 }
1141         }
1142
1143         snprintf(fulluser, sizeof(fulluser), "%s%s%s",
1144                          prefix, port->user_name, suffix);
1145         fulluser[sizeof(fulluser) - 1] = '\0';
1146
1147         r = ldap_simple_bind_s(ldap, fulluser, passwd);
1148         ldap_unbind(ldap);
1149
1150         if (r != LDAP_SUCCESS)
1151         {
1152                 ereport(LOG,
1153                                 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
1154                                                 fulluser, server, r)));
1155                 return STATUS_ERROR;
1156         }
1157
1158         return STATUS_OK;
1159 }
1160 #endif   /* USE_LDAP */
1161
1162 /*
1163  * Collect password response packet from frontend.
1164  *
1165  * Returns NULL if couldn't get password, else palloc'd string.
1166  */
1167 static char *
1168 recv_password_packet(Port *port)
1169 {
1170         StringInfoData buf;
1171
1172         if (PG_PROTOCOL_MAJOR(port->proto) >= 3)
1173         {
1174                 /* Expect 'p' message type */
1175                 int                     mtype;
1176
1177                 mtype = pq_getbyte();
1178                 if (mtype != 'p')
1179                 {
1180                         /*
1181                          * If the client just disconnects without offering a password,
1182                          * don't make a log entry.  This is legal per protocol spec and in
1183                          * fact commonly done by psql, so complaining just clutters the
1184                          * log.
1185                          */
1186                         if (mtype != EOF)
1187                                 ereport(COMMERROR,
1188                                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1189                                         errmsg("expected password response, got message type %d",
1190                                                    mtype)));
1191                         return NULL;            /* EOF or bad message type */
1192                 }
1193         }
1194         else
1195         {
1196                 /* For pre-3.0 clients, avoid log entry if they just disconnect */
1197                 if (pq_peekbyte() == EOF)
1198                         return NULL;            /* EOF */
1199         }
1200
1201         initStringInfo(&buf);
1202         if (pq_getmessage(&buf, 1000))          /* receive password */
1203         {
1204                 /* EOF - pq_getmessage already logged a suitable message */
1205                 pfree(buf.data);
1206                 return NULL;
1207         }
1208
1209         /*
1210          * Apply sanity check: password packet length should agree with length of
1211          * contained string.  Note it is safe to use strlen here because
1212          * StringInfo is guaranteed to have an appended '\0'.
1213          */
1214         if (strlen(buf.data) + 1 != buf.len)
1215                 ereport(COMMERROR,
1216                                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1217                                  errmsg("invalid password packet size")));
1218
1219         /* Do not echo password to logs, for security. */
1220         ereport(DEBUG5,
1221                         (errmsg("received password packet")));
1222
1223         /*
1224          * Return the received string.  Note we do not attempt to do any
1225          * character-set conversion on it; since we don't yet know the client's
1226          * encoding, there wouldn't be much point.
1227          */
1228         return buf.data;
1229 }
1230
1231
1232 /*
1233  * Called when we have sent an authorization request for a password.
1234  * Get the response and check it.
1235  */
1236 static int
1237 recv_and_check_password_packet(Port *port)
1238 {
1239         char       *passwd;
1240         int                     result;
1241
1242         passwd = recv_password_packet(port);
1243
1244         if (passwd == NULL)
1245                 return STATUS_EOF;              /* client wouldn't send password */
1246
1247         result = md5_crypt_verify(port, port->user_name, passwd);
1248
1249         pfree(passwd);
1250
1251         return result;
1252 }