]> granicus.if.org Git - postgresql/blob - src/interfaces/libpq/fe-auth.c
f3a177c985eea01820a8b8e82ed5202698f48c55
[postgresql] / src / interfaces / libpq / fe-auth.c
1 /*-------------------------------------------------------------------------
2  *
3  * fe-auth.c
4  *         The front-end (client) authorization routines
5  *
6  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.134 2007/12/04 13:02:53 mha Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14
15 /*
16  * INTERFACE ROUTINES
17  *         frontend (client) routines:
18  *              pg_fe_sendauth                  send authentication information
19  *              pg_fe_getauthname               get user's name according to the client side
20  *                                                              of the authentication system
21  */
22
23 #include "postgres_fe.h"
24
25 #ifdef WIN32
26 #include "win32.h"
27 #else
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #include <sys/param.h>                  /* for MAXHOSTNAMELEN on most */
32 #include <sys/socket.h>
33 #if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
34 #include <sys/uio.h>
35 #include <sys/ucred.h>
36 #endif
37 #ifndef  MAXHOSTNAMELEN
38 #include <netdb.h>                              /* for MAXHOSTNAMELEN on some */
39 #endif
40 #include <pwd.h>
41 #endif
42
43 #ifdef HAVE_CRYPT_H
44 #include <crypt.h>
45 #endif
46
47 #include "libpq-fe.h"
48 #include "fe-auth.h"
49 #include "libpq/md5.h"
50
51
52 #ifdef KRB5
53 /*
54  * MIT Kerberos authentication system - protocol version 5
55  */
56
57 #include <krb5.h>
58 /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
59 #if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
60 #include <com_err.h>
61 #endif
62
63 /*
64  * Heimdal doesn't have a free function for unparsed names. Just pass it to
65  * standard free() which should work in these cases.
66  */
67 #ifndef HAVE_KRB5_FREE_UNPARSED_NAME
68 static void
69 krb5_free_unparsed_name(krb5_context context, char *val)
70 {
71         free(val);
72 }
73 #endif
74
75 /*
76  * pg_an_to_ln -- return the local name corresponding to an authentication
77  *                                name
78  *
79  * XXX Assumes that the first aname component is the user name.  This is NOT
80  *         necessarily so, since an aname can actually be something out of your
81  *         worst X.400 nightmare, like
82  *                ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
83  *         Note that the MIT an_to_ln code does the same thing if you don't
84  *         provide an aname mapping database...it may be a better idea to use
85  *         krb5_an_to_ln, except that it punts if multiple components are found,
86  *         and we can't afford to punt.
87  *
88  * For WIN32, convert username to lowercase because the Win32 kerberos library
89  * generates tickets with the username as the user entered it instead of as
90  * it is entered in the directory.
91  */
92 static char *
93 pg_an_to_ln(char *aname)
94 {
95         char       *p;
96
97         if ((p = strchr(aname, '/')) || (p = strchr(aname, '@')))
98                 *p = '\0';
99 #ifdef WIN32
100         for (p = aname; *p; p++)
101                 *p = pg_tolower((unsigned char) *p);
102 #endif
103
104         return aname;
105 }
106
107
108 /*
109  * Various krb5 state which is not connection specific, and a flag to
110  * indicate whether we have initialised it yet.
111  */
112 /*
113 static int      pg_krb5_initialised;
114 static krb5_context pg_krb5_context;
115 static krb5_ccache pg_krb5_ccache;
116 static krb5_principal pg_krb5_client;
117 static char *pg_krb5_name;
118 */
119
120 struct krb5_info
121 {
122         int                     pg_krb5_initialised;
123         krb5_context pg_krb5_context;
124         krb5_ccache pg_krb5_ccache;
125         krb5_principal pg_krb5_client;
126         char       *pg_krb5_name;
127 };
128
129
130 static int
131 pg_krb5_init(PQExpBuffer errorMessage, struct krb5_info * info)
132 {
133         krb5_error_code retval;
134
135         if (info->pg_krb5_initialised)
136                 return STATUS_OK;
137
138         retval = krb5_init_context(&(info->pg_krb5_context));
139         if (retval)
140         {
141                 printfPQExpBuffer(errorMessage,
142                                                   "pg_krb5_init: krb5_init_context: %s\n",
143                                                   error_message(retval));
144                 return STATUS_ERROR;
145         }
146
147         retval = krb5_cc_default(info->pg_krb5_context, &(info->pg_krb5_ccache));
148         if (retval)
149         {
150                 printfPQExpBuffer(errorMessage,
151                                                   "pg_krb5_init: krb5_cc_default: %s\n",
152                                                   error_message(retval));
153                 krb5_free_context(info->pg_krb5_context);
154                 return STATUS_ERROR;
155         }
156
157         retval = krb5_cc_get_principal(info->pg_krb5_context, info->pg_krb5_ccache,
158                                                                    &(info->pg_krb5_client));
159         if (retval)
160         {
161                 printfPQExpBuffer(errorMessage,
162                                                   "pg_krb5_init: krb5_cc_get_principal: %s\n",
163                                                   error_message(retval));
164                 krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache);
165                 krb5_free_context(info->pg_krb5_context);
166                 return STATUS_ERROR;
167         }
168
169         retval = krb5_unparse_name(info->pg_krb5_context, info->pg_krb5_client, &(info->pg_krb5_name));
170         if (retval)
171         {
172                 printfPQExpBuffer(errorMessage,
173                                                   "pg_krb5_init: krb5_unparse_name: %s\n",
174                                                   error_message(retval));
175                 krb5_free_principal(info->pg_krb5_context, info->pg_krb5_client);
176                 krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache);
177                 krb5_free_context(info->pg_krb5_context);
178                 return STATUS_ERROR;
179         }
180
181         info->pg_krb5_name = pg_an_to_ln(info->pg_krb5_name);
182
183         info->pg_krb5_initialised = 1;
184         return STATUS_OK;
185 }
186
187 static void
188 pg_krb5_destroy(struct krb5_info * info)
189 {
190         krb5_free_principal(info->pg_krb5_context, info->pg_krb5_client);
191         krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache);
192         krb5_free_unparsed_name(info->pg_krb5_context, info->pg_krb5_name);
193         krb5_free_context(info->pg_krb5_context);
194 }
195
196
197
198 /*
199  * pg_krb5_authname -- returns a copy of whatever name the user
200  *                                         has authenticated to the system, or NULL
201  */
202 static char *
203 pg_krb5_authname(PQExpBuffer errorMessage)
204 {
205         char       *tmp_name;
206         struct krb5_info info;
207
208         info.pg_krb5_initialised = 0;
209
210         if (pg_krb5_init(errorMessage, &info) != STATUS_OK)
211                 return NULL;
212         tmp_name = strdup(info.pg_krb5_name);
213         pg_krb5_destroy(&info);
214
215         return tmp_name;
216 }
217
218
219 /*
220  * pg_krb5_sendauth -- client routine to send authentication information to
221  *                                         the server
222  */
223 static int
224 pg_krb5_sendauth(PGconn *conn)
225 {
226         krb5_error_code retval;
227         int                     ret;
228         krb5_principal server;
229         krb5_auth_context auth_context = NULL;
230         krb5_error *err_ret = NULL;
231         struct krb5_info info;
232
233         info.pg_krb5_initialised = 0;
234
235         if (!conn->pghost)
236         {
237                 printfPQExpBuffer(&conn->errorMessage,
238                                                   "pg_krb5_sendauth: hostname must be specified for Kerberos authentication\n");
239                 return STATUS_ERROR;
240         }
241
242         ret = pg_krb5_init(&conn->errorMessage, &info);
243         if (ret != STATUS_OK)
244                 return ret;
245
246         retval = krb5_sname_to_principal(info.pg_krb5_context, conn->pghost,
247                                                                          conn->krbsrvname,
248                                                                          KRB5_NT_SRV_HST, &server);
249         if (retval)
250         {
251                 printfPQExpBuffer(&conn->errorMessage,
252                                                   "pg_krb5_sendauth: krb5_sname_to_principal: %s\n",
253                                                   error_message(retval));
254                 pg_krb5_destroy(&info);
255                 return STATUS_ERROR;
256         }
257
258         /*
259          * libpq uses a non-blocking socket. But kerberos needs a blocking socket,
260          * and we have to block somehow to do mutual authentication anyway. So we
261          * temporarily make it blocking.
262          */
263         if (!pg_set_block(conn->sock))
264         {
265                 char            sebuf[256];
266
267                 printfPQExpBuffer(&conn->errorMessage,
268                                                   libpq_gettext("could not set socket to blocking mode: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf)));
269                 krb5_free_principal(info.pg_krb5_context, server);
270                 pg_krb5_destroy(&info);
271                 return STATUS_ERROR;
272         }
273
274         retval = krb5_sendauth(info.pg_krb5_context, &auth_context,
275                                           (krb5_pointer) & conn->sock, (char *) conn->krbsrvname,
276                                                    info.pg_krb5_client, server,
277                                                    AP_OPTS_MUTUAL_REQUIRED,
278                                                    NULL, 0,             /* no creds, use ccache instead */
279                                                    info.pg_krb5_ccache, &err_ret, NULL, NULL);
280         if (retval)
281         {
282                 if (retval == KRB5_SENDAUTH_REJECTED && err_ret)
283                 {
284 #if defined(HAVE_KRB5_ERROR_TEXT_DATA)
285                         printfPQExpBuffer(&conn->errorMessage,
286                                   libpq_gettext("Kerberos 5 authentication rejected: %*s\n"),
287                                                           (int) err_ret->text.length, err_ret->text.data);
288 #elif defined(HAVE_KRB5_ERROR_E_DATA)
289                         printfPQExpBuffer(&conn->errorMessage,
290                                   libpq_gettext("Kerberos 5 authentication rejected: %*s\n"),
291                                                           (int) err_ret->e_data->length,
292                                                           (const char *) err_ret->e_data->data);
293 #else
294 #error "bogus configuration"
295 #endif
296                 }
297                 else
298                 {
299                         printfPQExpBuffer(&conn->errorMessage,
300                                                           "krb5_sendauth: %s\n", error_message(retval));
301                 }
302
303                 if (err_ret)
304                         krb5_free_error(info.pg_krb5_context, err_ret);
305
306                 ret = STATUS_ERROR;
307         }
308
309         krb5_free_principal(info.pg_krb5_context, server);
310
311         if (!pg_set_noblock(conn->sock))
312         {
313                 char            sebuf[256];
314
315                 printfPQExpBuffer(&conn->errorMessage,
316                 libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
317                                                   pqStrerror(errno, sebuf, sizeof(sebuf)));
318                 ret = STATUS_ERROR;
319         }
320         pg_krb5_destroy(&info);
321
322         return ret;
323 }
324 #endif   /* KRB5 */
325
326 #ifdef ENABLE_GSS
327 /*
328  * GSSAPI authentication system.
329  */
330
331 #if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
332 /*
333  * MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
334  * that contain the OIDs required. Redefine here, values copied
335  * from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
336  */
337 static const gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_desc =
338 {10, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"};
339 static GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE = &GSS_C_NT_HOSTBASED_SERVICE_desc;
340 #endif
341
342 /*
343  * Fetch all errors of a specific type that fit into a buffer
344  * and append them.
345  */
346 static void
347 pg_GSS_error_int(char *mprefix, char *msg, int msglen,
348                                  OM_uint32 stat, int type)
349 {
350         int                     curlen = 0;
351         OM_uint32       lmaj_s,
352                                 lmin_s;
353         gss_buffer_desc lmsg;
354         OM_uint32       msg_ctx = 0;
355
356         do
357         {
358                 lmaj_s = gss_display_status(&lmin_s, stat, type,
359                                                                         GSS_C_NO_OID, &msg_ctx, &lmsg);
360
361                 if (curlen < msglen)
362                 {
363                         snprintf(msg + curlen, msglen - curlen, "%s: %s\n",
364                                          mprefix, (char *) lmsg.value);
365                         curlen += lmsg.length;
366                 }
367                 gss_release_buffer(&lmin_s, &lmsg);
368         } while (msg_ctx);
369 }
370
371 /*
372  * GSSAPI errors contains two parts. Put as much as possible of
373  * both parts into the string.
374  */
375 static void
376 pg_GSS_error(char *mprefix, PGconn *conn,
377                          OM_uint32 maj_stat, OM_uint32 min_stat)
378 {
379         int                     mlen;
380
381         /* Fetch major error codes */
382         pg_GSS_error_int(mprefix, conn->errorMessage.data,
383                                          conn->errorMessage.maxlen, maj_stat, GSS_C_GSS_CODE);
384         mlen = strlen(conn->errorMessage.data);
385
386         /* If there is room left, try to add the minor codes as well */
387         if (mlen < conn->errorMessage.maxlen - 1)
388                 pg_GSS_error_int(mprefix, conn->errorMessage.data + mlen,
389                                 conn->errorMessage.maxlen - mlen, min_stat, GSS_C_MECH_CODE);
390 }
391
392 /*
393  * Continue GSS authentication with next token as needed.
394  */
395 static int
396 pg_GSS_continue(PGconn *conn)
397 {
398         OM_uint32       maj_stat,
399                                 min_stat,
400                                 lmin_s;
401
402         maj_stat = gss_init_sec_context(&min_stat,
403                                                                         GSS_C_NO_CREDENTIAL,
404                                                                         &conn->gctx,
405                                                                         conn->gtarg_nam,
406                                                                         GSS_C_NO_OID,
407                                                                         GSS_C_MUTUAL_FLAG,
408                                                                         0,
409                                                                         GSS_C_NO_CHANNEL_BINDINGS,
410                   (conn->gctx == GSS_C_NO_CONTEXT) ? GSS_C_NO_BUFFER : &conn->ginbuf,
411                                                                         NULL,
412                                                                         &conn->goutbuf,
413                                                                         NULL,
414                                                                         NULL);
415
416         if (conn->gctx != GSS_C_NO_CONTEXT)
417         {
418                 free(conn->ginbuf.value);
419                 conn->ginbuf.value = NULL;
420                 conn->ginbuf.length = 0;
421         }
422
423         if (conn->goutbuf.length != 0)
424         {
425                 /*
426                  * GSS generated data to send to the server. We don't care if it's the
427                  * first or subsequent packet, just send the same kind of password
428                  * packet.
429                  */
430                 if (pqPacketSend(conn, 'p',
431                                                  conn->goutbuf.value, conn->goutbuf.length)
432                         != STATUS_OK)
433                 {
434                         gss_release_buffer(&lmin_s, &conn->goutbuf);
435                         return STATUS_ERROR;
436                 }
437         }
438         gss_release_buffer(&lmin_s, &conn->goutbuf);
439
440         if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
441         {
442                 pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
443                                          conn,
444                                          maj_stat, min_stat);
445                 gss_release_name(&lmin_s, &conn->gtarg_nam);
446                 if (conn->gctx)
447                         gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
448                 return STATUS_ERROR;
449         }
450
451         if (maj_stat == GSS_S_COMPLETE)
452                 gss_release_name(&lmin_s, &conn->gtarg_nam);
453
454         return STATUS_OK;
455 }
456
457 /*
458  * Send initial GSS authentication token
459  */
460 static int
461 pg_GSS_startup(PGconn *conn)
462 {
463         OM_uint32       maj_stat,
464                                 min_stat;
465         int                     maxlen;
466         gss_buffer_desc temp_gbuf;
467
468         if (conn->gctx)
469         {
470                 printfPQExpBuffer(&conn->errorMessage,
471                                         libpq_gettext("duplicate GSS authentication request\n"));
472                 return STATUS_ERROR;
473         }
474
475         /*
476          * Import service principal name so the proper ticket can be acquired by
477          * the GSSAPI system.
478          */
479         maxlen = NI_MAXHOST + strlen(conn->krbsrvname) + 2;
480         temp_gbuf.value = (char *) malloc(maxlen);
481         snprintf(temp_gbuf.value, maxlen, "%s@%s",
482                          conn->krbsrvname, conn->pghost);
483         temp_gbuf.length = strlen(temp_gbuf.value);
484
485         maj_stat = gss_import_name(&min_stat, &temp_gbuf,
486                                                            GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam);
487         free(temp_gbuf.value);
488
489         if (maj_stat != GSS_S_COMPLETE)
490         {
491                 pg_GSS_error(libpq_gettext("GSSAPI name import error"),
492                                          conn,
493                                          maj_stat, min_stat);
494                 return STATUS_ERROR;
495         }
496
497         /*
498          * Initial packet is the same as a continuation packet with no initial
499          * context.
500          */
501         conn->gctx = GSS_C_NO_CONTEXT;
502
503         return pg_GSS_continue(conn);
504 }
505 #endif   /* ENABLE_GSS */
506
507
508 #ifdef ENABLE_SSPI
509 /*
510  * SSPI authentication system (Windows only)
511  */
512
513 static void
514 pg_SSPI_error(PGconn *conn, char *mprefix, SECURITY_STATUS r)
515 {
516         char            sysmsg[256];
517
518         if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, r, 0,
519                                           sysmsg, sizeof(sysmsg), NULL) == 0)
520                 printfPQExpBuffer(&conn->errorMessage, "%s: sspi error %x",
521                                                   mprefix, (unsigned int) r);
522         else
523                 printfPQExpBuffer(&conn->errorMessage, "%s: %s (%x)",
524                                                   mprefix, sysmsg, (unsigned int) r);
525 }
526
527 /*
528  * Continue SSPI authentication with next token as needed.
529  */
530 static int
531 pg_SSPI_continue(PGconn *conn)
532 {
533         SECURITY_STATUS r;
534         CtxtHandle      newContext;
535         ULONG           contextAttr;
536         SecBufferDesc inbuf;
537         SecBufferDesc outbuf;
538         SecBuffer       OutBuffers[1];
539         SecBuffer       InBuffers[1];
540
541         if (conn->sspictx != NULL)
542         {
543                 /*
544                  * On runs other than the first we have some data to send. Put this
545                  * data in a SecBuffer type structure.
546                  */
547                 inbuf.ulVersion = SECBUFFER_VERSION;
548                 inbuf.cBuffers = 1;
549                 inbuf.pBuffers = InBuffers;
550                 InBuffers[0].pvBuffer = conn->ginbuf.value;
551                 InBuffers[0].cbBuffer = conn->ginbuf.length;
552                 InBuffers[0].BufferType = SECBUFFER_TOKEN;
553         }
554
555         OutBuffers[0].pvBuffer = NULL;
556         OutBuffers[0].BufferType = SECBUFFER_TOKEN;
557         OutBuffers[0].cbBuffer = 0;
558         outbuf.cBuffers = 1;
559         outbuf.pBuffers = OutBuffers;
560         outbuf.ulVersion = SECBUFFER_VERSION;
561
562         r = InitializeSecurityContext(conn->sspicred,
563                                                                   conn->sspictx,
564                                                                   conn->sspitarget,
565                                                                   ISC_REQ_ALLOCATE_MEMORY,
566                                                                   0,
567                                                                   SECURITY_NETWORK_DREP,
568                                                                   (conn->sspictx == NULL) ? NULL : &inbuf,
569                                                                   0,
570                                                                   &newContext,
571                                                                   &outbuf,
572                                                                   &contextAttr,
573                                                                   NULL);
574
575         if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
576         {
577                 pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r);
578
579                 return STATUS_ERROR;
580         }
581
582         if (conn->sspictx == NULL)
583         {
584                 /* On first run, transfer retreived context handle */
585                 conn->sspictx = malloc(sizeof(CtxtHandle));
586                 if (conn->sspictx == NULL)
587                 {
588                         printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
589                         return STATUS_ERROR;
590                 }
591                 memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
592         }
593         else
594         {
595                 /*
596                  * On subsequent runs when we had data to send, free buffers that
597                  * contained this data.
598                  */
599                 free(conn->ginbuf.value);
600                 conn->ginbuf.value = NULL;
601                 conn->ginbuf.length = 0;
602         }
603
604         /*
605          * If SSPI returned any data to be sent to the server (as it normally
606          * would), send this data as a password packet.
607          */
608         if (outbuf.cBuffers > 0)
609         {
610                 if (outbuf.cBuffers != 1)
611                 {
612                         /*
613                          * This should never happen, at least not for Kerberos
614                          * authentication. Keep check in case it shows up with other
615                          * authentication methods later.
616                          */
617                         printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n");
618                         return STATUS_ERROR;
619                 }
620
621                 /*
622                  * If the negotiation is complete, there may be zero bytes to send. The server is
623                  * at this point not expecting any more data, so don't send it.
624                  */
625                 if (outbuf.pBuffers[0].cbBuffer > 0)
626                 {
627                         if (pqPacketSend(conn, 'p',
628                                            outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
629                         {
630                                 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
631                                 return STATUS_ERROR;
632                         }
633                 }
634                 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
635         }
636
637         /* Cleanup is handled by the code in freePGconn() */
638         return STATUS_OK;
639 }
640
641 /*
642  * Send initial SSPI authentication token.
643  * If use_negotiate is 0, use kerberos authentication package which is
644  * compatible with Unix. If use_negotiate is 1, use the negotiate package
645  * which supports both kerberos and NTLM, but is not compatible with Unix.
646  */
647 static int
648 pg_SSPI_startup(PGconn *conn, int use_negotiate)
649 {
650         SECURITY_STATUS r;
651         TimeStamp       expire;
652
653         conn->sspictx = NULL;
654
655         /*
656          * Retreive credentials handle
657          */
658         conn->sspicred = malloc(sizeof(CredHandle));
659         if (conn->sspicred == NULL)
660         {
661                 printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
662                 return STATUS_ERROR;
663         }
664
665         r = AcquireCredentialsHandle(NULL, use_negotiate ? "negotiate" : "kerberos", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, conn->sspicred, &expire);
666         if (r != SEC_E_OK)
667         {
668                 pg_SSPI_error(conn, "acquire credentials failed", r);
669                 free(conn->sspicred);
670                 conn->sspicred = NULL;
671                 return STATUS_ERROR;
672         }
673
674         /*
675          * Compute target principal name. SSPI has a different format from GSSAPI,
676          * but not more complex. We can skip the @REALM part, because Windows will
677          * fill that in for us automatically.
678          */
679         if (conn->pghost == NULL)
680         {
681                 printfPQExpBuffer(&conn->errorMessage, libpq_gettext("host name must be specified\n"));
682                 return STATUS_ERROR;
683         }
684         conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(conn->pghost) + 2);
685         if (!conn->sspitarget)
686         {
687                 printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
688                 return STATUS_ERROR;
689         }
690         sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, conn->pghost);
691
692         /*
693          * Indicate that we're in SSPI authentication mode to make sure that
694          * pg_SSPI_continue is called next time in the negotiation.
695          */
696         conn->usesspi = 1;
697
698         return pg_SSPI_continue(conn);
699 }
700 #endif   /* ENABLE_SSPI */
701
702 /*
703  * Respond to AUTH_REQ_SCM_CREDS challenge.
704  *
705  * Note: current backends will not use this challenge if HAVE_GETPEEREID
706  * or SO_PEERCRED is defined, but pre-7.4 backends might, so compile the
707  * code anyway.
708  */
709 static int
710 pg_local_sendauth(PGconn *conn)
711 {
712 #if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
713         (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
714         char            buf;
715         struct iovec iov;
716         struct msghdr msg;
717
718 #ifdef HAVE_STRUCT_CMSGCRED
719         /* Prevent padding */
720         char            cmsgmem[sizeof(struct cmsghdr) + sizeof(struct cmsgcred)];
721
722         /* Point to start of first structure */
723         struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
724 #endif
725
726         /*
727          * The backend doesn't care what we send here, but it wants exactly one
728          * character to force recvmsg() to block and wait for us.
729          */
730         buf = '\0';
731         iov.iov_base = &buf;
732         iov.iov_len = 1;
733
734         memset(&msg, 0, sizeof(msg));
735         msg.msg_iov = &iov;
736         msg.msg_iovlen = 1;
737
738 #ifdef HAVE_STRUCT_CMSGCRED
739         /* Create control header, FreeBSD */
740         msg.msg_control = cmsg;
741         msg.msg_controllen = sizeof(cmsgmem);
742         memset(cmsg, 0, sizeof(cmsgmem));
743         cmsg->cmsg_len = sizeof(cmsgmem);
744         cmsg->cmsg_level = SOL_SOCKET;
745         cmsg->cmsg_type = SCM_CREDS;
746 #endif
747
748         if (sendmsg(conn->sock, &msg, 0) == -1)
749         {
750                 char            sebuf[256];
751
752                 printfPQExpBuffer(&conn->errorMessage,
753                                                   "pg_local_sendauth: sendmsg: %s\n",
754                                                   pqStrerror(errno, sebuf, sizeof(sebuf)));
755                 return STATUS_ERROR;
756         }
757         return STATUS_OK;
758 #else
759         printfPQExpBuffer(&conn->errorMessage,
760                         libpq_gettext("SCM_CRED authentication method not supported\n"));
761         return STATUS_ERROR;
762 #endif
763 }
764
765 static int
766 pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
767 {
768         int                     ret;
769         char       *crypt_pwd;
770
771         /* Encrypt the password if needed. */
772
773         switch (areq)
774         {
775                 case AUTH_REQ_MD5:
776                         {
777                                 char       *crypt_pwd2;
778
779                                 /* Allocate enough space for two MD5 hashes */
780                                 crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
781                                 if (!crypt_pwd)
782                                 {
783                                         printfPQExpBuffer(&conn->errorMessage,
784                                                                           libpq_gettext("out of memory\n"));
785                                         return STATUS_ERROR;
786                                 }
787
788                                 crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1;
789                                 if (!pg_md5_encrypt(password, conn->pguser,
790                                                                         strlen(conn->pguser), crypt_pwd2))
791                                 {
792                                         free(crypt_pwd);
793                                         return STATUS_ERROR;
794                                 }
795                                 if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), conn->md5Salt,
796                                                                         sizeof(conn->md5Salt), crypt_pwd))
797                                 {
798                                         free(crypt_pwd);
799                                         return STATUS_ERROR;
800                                 }
801                                 break;
802                         }
803                 case AUTH_REQ_CRYPT:
804                         {
805                                 char            salt[3];
806
807                                 strlcpy(salt, conn->cryptSalt, sizeof(salt));
808                                 crypt_pwd = crypt(password, salt);
809                                 break;
810                         }
811                 case AUTH_REQ_PASSWORD:
812                         /* discard const so we can assign it */
813                         crypt_pwd = (char *) password;
814                         break;
815                 default:
816                         return STATUS_ERROR;
817         }
818         /* Packet has a message type as of protocol 3.0 */
819         if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
820                 ret = pqPacketSend(conn, 'p', crypt_pwd, strlen(crypt_pwd) + 1);
821         else
822                 ret = pqPacketSend(conn, 0, crypt_pwd, strlen(crypt_pwd) + 1);
823         if (areq == AUTH_REQ_MD5)
824                 free(crypt_pwd);
825         return ret;
826 }
827
828 /*
829  * pg_fe_sendauth
830  *              client demux routine for outgoing authentication information
831  */
832 int
833 pg_fe_sendauth(AuthRequest areq, PGconn *conn)
834 {
835         switch (areq)
836         {
837                 case AUTH_REQ_OK:
838                         break;
839
840                 case AUTH_REQ_KRB4:
841                         printfPQExpBuffer(&conn->errorMessage,
842                                  libpq_gettext("Kerberos 4 authentication not supported\n"));
843                         return STATUS_ERROR;
844
845                 case AUTH_REQ_KRB5:
846 #ifdef KRB5
847                         pglock_thread();
848                         if (pg_krb5_sendauth(conn) != STATUS_OK)
849                         {
850                                 /* Error message already filled in */
851                                 pgunlock_thread();
852                                 return STATUS_ERROR;
853                         }
854                         pgunlock_thread();
855                         break;
856 #else
857                         printfPQExpBuffer(&conn->errorMessage,
858                                  libpq_gettext("Kerberos 5 authentication not supported\n"));
859                         return STATUS_ERROR;
860 #endif
861
862 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
863                 case AUTH_REQ_GSS:
864                         {
865                                 int                     r;
866
867                                 pglock_thread();
868
869                                 /*
870                                  * If we have both GSS and SSPI support compiled in, use SSPI
871                                  * support by default. This is overridable by a connection
872                                  * string parameter. Note that when using SSPI we still leave
873                                  * the negotiate parameter off, since we want SSPI to use the
874                                  * GSSAPI kerberos protocol. For actual SSPI negotiate
875                                  * protocol, we use AUTH_REQ_SSPI.
876                                  */
877 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
878                                 if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
879                                         r = pg_GSS_startup(conn);
880                                 else
881                                         r = pg_SSPI_startup(conn, 0);
882 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
883                                 r = pg_GSS_startup(conn);
884 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
885                                 r = pg_SSPI_startup(conn, 0);
886 #endif
887                                 if (r != STATUS_OK)
888                                 {
889                                         /* Error message already filled in. */
890                                         pgunlock_thread();
891                                         return STATUS_ERROR;
892                                 }
893                                 pgunlock_thread();
894                         }
895                         break;
896
897                 case AUTH_REQ_GSS_CONT:
898                         {
899                                 int                     r;
900
901                                 pglock_thread();
902 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
903                                 if (conn->usesspi)
904                                         r = pg_SSPI_continue(conn);
905                                 else
906                                         r = pg_GSS_continue(conn);
907 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
908                                 r = pg_GSS_continue(conn);
909 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
910                                 r = pg_SSPI_continue(conn);
911 #endif
912                                 if (r != STATUS_OK)
913                                 {
914                                         /* Error message already filled in. */
915                                         pgunlock_thread();
916                                         return STATUS_ERROR;
917                                 }
918                                 pgunlock_thread();
919                         }
920                         break;
921 #else
922                 case AUTH_REQ_GSS:
923                 case AUTH_REQ_GSS_CONT:
924                         printfPQExpBuffer(&conn->errorMessage,
925                                          libpq_gettext("GSSAPI authentication not supported\n"));
926                         return STATUS_ERROR;
927 #endif
928
929 #ifdef ENABLE_SSPI
930                 case AUTH_REQ_SSPI:
931
932                         /*
933                          * SSPI has it's own startup message so libpq can decide which
934                          * method to use. Indicate to pg_SSPI_startup that we want SSPI
935                          * negotiation instead of Kerberos.
936                          */
937                         pglock_thread();
938                         if (pg_SSPI_startup(conn, 1) != STATUS_OK)
939                         {
940                                 /* Error message already filled in. */
941                                 pgunlock_thread();
942                                 return STATUS_ERROR;
943                         }
944                         pgunlock_thread();
945                         break;
946 #else
947                 case AUTH_REQ_SSPI:
948                         printfPQExpBuffer(&conn->errorMessage,
949                                            libpq_gettext("SSPI authentication not supported\n"));
950                         return STATUS_ERROR;
951 #endif
952
953
954                 case AUTH_REQ_MD5:
955                 case AUTH_REQ_CRYPT:
956                 case AUTH_REQ_PASSWORD:
957                         if (conn->pgpass == NULL || *conn->pgpass == '\0')
958                         {
959                                 printfPQExpBuffer(&conn->errorMessage,
960                                                                   PQnoPasswordSupplied);
961                                 return STATUS_ERROR;
962                         }
963                         if (pg_password_sendauth(conn, conn->pgpass, areq) != STATUS_OK)
964                         {
965                                 printfPQExpBuffer(&conn->errorMessage,
966                                          "fe_sendauth: error sending password authentication\n");
967                                 return STATUS_ERROR;
968                         }
969                         break;
970
971                 case AUTH_REQ_SCM_CREDS:
972                         if (pg_local_sendauth(conn) != STATUS_OK)
973                                 return STATUS_ERROR;
974                         break;
975
976                 default:
977                         printfPQExpBuffer(&conn->errorMessage,
978                         libpq_gettext("authentication method %u not supported\n"), areq);
979                         return STATUS_ERROR;
980         }
981
982         return STATUS_OK;
983 }
984
985
986 /*
987  * pg_fe_getauthname -- returns a pointer to dynamic space containing whatever
988  *                                       name the user has authenticated to the system
989  *
990  * if there is an error, return NULL with an error message in errorMessage
991  */
992 char *
993 pg_fe_getauthname(PQExpBuffer errorMessage)
994 {
995 #ifdef KRB5
996         char       *krb5_name = NULL;
997 #endif
998         const char *name = NULL;
999         char       *authn;
1000
1001 #ifdef WIN32
1002         char            username[128];
1003         DWORD           namesize = sizeof(username) - 1;
1004 #else
1005         char            pwdbuf[BUFSIZ];
1006         struct passwd pwdstr;
1007         struct passwd *pw = NULL;
1008 #endif
1009
1010         /*
1011          * pglock_thread() really only needs to be called around
1012          * pg_krb5_authname(), but some users are using configure
1013          * --enable-thread-safety-force, so we might as well do the locking within
1014          * our library to protect pqGetpwuid(). In fact, application developers
1015          * can use getpwuid() in their application if they use the locking call we
1016          * provide, or install their own locking function using
1017          * PQregisterThreadLock().
1018          */
1019         pglock_thread();
1020
1021 #ifdef KRB5
1022
1023         /*
1024          * pg_krb5_authname gives us a strdup'd value that we need to free later,
1025          * however, we don't want to free 'name' directly in case it's *not* a
1026          * Kerberos login and we fall through to name = pw->pw_name;
1027          */
1028         krb5_name = pg_krb5_authname(errorMessage);
1029         name = krb5_name;
1030 #endif
1031
1032         if (!name)
1033         {
1034 #ifdef WIN32
1035                 if (GetUserName(username, &namesize))
1036                         name = username;
1037 #else
1038                 if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pw) == 0)
1039                         name = pw->pw_name;
1040 #endif
1041         }
1042
1043         authn = name ? strdup(name) : NULL;
1044
1045 #ifdef KRB5
1046         /* Free the strdup'd string from pg_krb5_authname, if we got one */
1047         if (krb5_name)
1048                 free(krb5_name);
1049 #endif
1050
1051         pgunlock_thread();
1052
1053         return authn;
1054 }
1055
1056
1057 /*
1058  * PQencryptPassword -- exported routine to encrypt a password
1059  *
1060  * This is intended to be used by client applications that wish to send
1061  * commands like ALTER USER joe PASSWORD 'pwd'.  The password need not
1062  * be sent in cleartext if it is encrypted on the client side.  This is
1063  * good because it ensures the cleartext password won't end up in logs,
1064  * pg_stat displays, etc.  We export the function so that clients won't
1065  * be dependent on low-level details like whether the enceyption is MD5
1066  * or something else.
1067  *
1068  * Arguments are the cleartext password, and the SQL name of the user it
1069  * is for.
1070  *
1071  * Return value is a malloc'd string, or NULL if out-of-memory.  The client
1072  * may assume the string doesn't contain any special characters that would
1073  * require escaping.
1074  */
1075 char *
1076 PQencryptPassword(const char *passwd, const char *user)
1077 {
1078         char       *crypt_pwd;
1079
1080         crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
1081         if (!crypt_pwd)
1082                 return NULL;
1083
1084         if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
1085         {
1086                 free(crypt_pwd);
1087                 return NULL;
1088         }
1089
1090         return crypt_pwd;
1091 }