On Mon, Jul 23, 2007 at 03:36:21PM +0200, Magnus Hagander wrote:
> I've been debugging some really weird crashes in libpq on win32, and I
> think I've finally found the reason for the heap corruption that shows up
> in msvc debug mode.
>
> When run in debug mode, the runtime for msvc will *zero-pad the entire
> buffer* in a strncpy() call. This in itself is not bad (just slow), but it
> shows a rather bad bug in libpq.
>
> In a bunch of places in fe-auth.c, we do:
> strncpy(PQerrormsg, libpq_gettext("out of memory\n"), PQERRORMSG_LENGTH);
>
>
> Except when calling it, the size of the buffer is 256 bytes. But
> PQERRORMSG_LENGTH is 1024.
>
> Naturally, this causes a heap corruption. It doesn't happen in production,
> because the string length fits as long as there is no padding.
>
> One way to get around this on win32 is to just use snprintf() instead of
> strncpy(), since it doesn't pad. But that's just hiding the underlying
> problem, so I think that's a really bad fix.
>
> I assume the comment in the header:
> * NOTE: the error message strings returned by this module must not
> * exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
>
> refers to this, but it's hard to guarantee that from the code since it's
> translated strings.
>
> I see a comment in fe-connect.c that has
> * XXX fe-auth.c has not been fixed to support PQExpBuffers,
>
>
> Given this, I'll go ahead and fix fe-connect to support PQExpBuffers,
> unless there are any objections. Also, is this something we shuold
> backpatch - or just ignore since we've had no actual reports of it in the
> field?
Actually coding up a patch for that was just a bunch of simple
search/replace ops. Attached is one that appears to work fine for me.
Actually coding up a patch for that was just a bunch of simple
search/replace ops. Attached is one that appears to work fine for me.
Was there any reason why this wasn't done before, or just nobody had the
time? If there was a reason, please let me know what it was :-) Otherwise
I'll apply this patch to fix it.
(Question about backpatch remains)
//Magnus
Index: src/interfaces/libpq/fe-auth.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v
retrieving revision 1.129
diff -c -r1.129 fe-auth.c
*** src/interfaces/libpq/fe-auth.c 23 Jul 2007 10:57:36 -0000 1.129
--- src/interfaces/libpq/fe-auth.c 23 Jul 2007 14:02:28 -0000
***************
*** 6,14 ****
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * NOTE: the error message strings returned by this module must not
- * exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
- *
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.129 2007/07/23
10:57:36 mha Exp $
*
--- 6,11 ----
***************
*** 131,137 ****
static int
! pg_krb5_init(char *PQerrormsg, struct krb5_info * info)
{
krb5_error_code retval;
--- 128,134 ----
static int
! pg_krb5_init(PQExpBuffer errorMessage, struct krb5_info * info)
{
krb5_error_code retval;
***************
*** 141,147 ****
retval = krb5_init_context(&(info->pg_krb5_context));
if (retval)
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"pg_krb5_init: krb5_init_context: %s\n",
error_message(retval));
return STATUS_ERROR;
--- 138,144 ----
retval = krb5_init_context(&(info->pg_krb5_context));
if (retval)
{
! printfPQExpBuffer(errorMessage,
"pg_krb5_init: krb5_init_context: %s\n",
error_message(retval));
return STATUS_ERROR;
***************
*** 150,156 ****
retval = krb5_cc_default(info->pg_krb5_context,
&(info->pg_krb5_ccache));
if (retval)
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"pg_krb5_init: krb5_cc_default: %s\n",
error_message(retval));
krb5_free_context(info->pg_krb5_context);
--- 147,153 ----
retval = krb5_cc_default(info->pg_krb5_context,
&(info->pg_krb5_ccache));
if (retval)
{
! printfPQExpBuffer(errorMessage,
"pg_krb5_init: krb5_cc_default: %s\n",
error_message(retval));
krb5_free_context(info->pg_krb5_context);
***************
*** 161,167 ****
&(info->pg_krb5_client));
if (retval)
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"pg_krb5_init: krb5_cc_get_principal: %s\n",
error_message(retval));
krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache);
--- 158,164 ----
&(info->pg_krb5_client));
if (retval)
{
! printfPQExpBuffer(errorMessage,
"pg_krb5_init: krb5_cc_get_principal: %s\n",
error_message(retval));
krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache);
***************
*** 172,178 ****
retval = krb5_unparse_name(info->pg_krb5_context, info->pg_krb5_client,
&(info->pg_krb5_name));
if (retval)
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"pg_krb5_init: krb5_unparse_name: %s\n",
error_message(retval));
krb5_free_principal(info->pg_krb5_context,
info->pg_krb5_client);
--- 169,175 ----
retval = krb5_unparse_name(info->pg_krb5_context, info->pg_krb5_client,
&(info->pg_krb5_name));
if (retval)
{
! printfPQExpBuffer(errorMessage,
"pg_krb5_init: krb5_unparse_name: %s\n",
error_message(retval));
krb5_free_principal(info->pg_krb5_context,
info->pg_krb5_client);
***************
*** 203,216 ****
* has authenticated to the system, or
NULL
*/
static char *
! pg_krb5_authname(char *PQerrormsg)
{
char *tmp_name;
struct krb5_info info;
info.pg_krb5_initialised = 0;
! if (pg_krb5_init(PQerrormsg, &info) != STATUS_OK)
return NULL;
tmp_name = strdup(info.pg_krb5_name);
pg_krb5_destroy(&info);
--- 200,213 ----
* has authenticated to the system, or
NULL
*/
static char *
! pg_krb5_authname(PQExpBuffer errorMessage)
{
char *tmp_name;
struct krb5_info info;
info.pg_krb5_initialised = 0;
! if (pg_krb5_init(errorMessage, &info) != STATUS_OK)
return NULL;
tmp_name = strdup(info.pg_krb5_name);
pg_krb5_destroy(&info);
***************
*** 224,230 ****
* the server
*/
static int
! pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname, const char
*servicename)
{
krb5_error_code retval;
int ret;
--- 221,227 ----
* the server
*/
static int
! pg_krb5_sendauth(PGconn *conn, int sock, const char *hostname, const char
*servicename)
{
krb5_error_code retval;
int ret;
***************
*** 237,248 ****
if (!hostname)
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"pg_krb5_sendauth: hostname must be specified
for Kerberos authentication\n");
return STATUS_ERROR;
}
! ret = pg_krb5_init(PQerrormsg, &info);
if (ret != STATUS_OK)
return ret;
--- 234,245 ----
if (!hostname)
{
! printfPQExpBuffer(&conn->errorMessage,
"pg_krb5_sendauth: hostname must be specified
for Kerberos authentication\n");
return STATUS_ERROR;
}
! ret = pg_krb5_init(&conn->errorMessage, &info);
if (ret != STATUS_OK)
return ret;
***************
*** 250,256 ****
KRB5_NT_SRV_HST, &server);
if (retval)
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"pg_krb5_sendauth: krb5_sname_to_principal:
%s\n",
error_message(retval));
pg_krb5_destroy(&info);
--- 247,253 ----
KRB5_NT_SRV_HST, &server);
if (retval)
{
! printfPQExpBuffer(&conn->errorMessage,
"pg_krb5_sendauth: krb5_sname_to_principal:
%s\n",
error_message(retval));
pg_krb5_destroy(&info);
***************
*** 266,272 ****
{
char sebuf[256];
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not set socket to
blocking mode: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf)));
krb5_free_principal(info.pg_krb5_context, server);
pg_krb5_destroy(&info);
--- 263,269 ----
{
char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to
blocking mode: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf)));
krb5_free_principal(info.pg_krb5_context, server);
pg_krb5_destroy(&info);
***************
*** 284,294 ****
if (retval == KRB5_SENDAUTH_REJECTED && err_ret)
{
#if defined(HAVE_KRB5_ERROR_TEXT_DATA)
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("Kerberos 5 authentication
rejected: %*s\n"),
(int) err_ret->text.length,
err_ret->text.data);
#elif defined(HAVE_KRB5_ERROR_E_DATA)
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("Kerberos 5 authentication
rejected: %*s\n"),
(int) err_ret->e_data->length,
(const char *) err_ret->e_data->data);
--- 281,291 ----
if (retval == KRB5_SENDAUTH_REJECTED && err_ret)
{
#if defined(HAVE_KRB5_ERROR_TEXT_DATA)
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Kerberos 5 authentication
rejected: %*s\n"),
(int) err_ret->text.length,
err_ret->text.data);
#elif defined(HAVE_KRB5_ERROR_E_DATA)
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Kerberos 5 authentication
rejected: %*s\n"),
(int) err_ret->e_data->length,
(const char *) err_ret->e_data->data);
***************
*** 298,304 ****
}
else
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"krb5_sendauth: %s\n",
error_message(retval));
}
--- 295,301 ----
}
else
{
! printfPQExpBuffer(&conn->errorMessage,
"krb5_sendauth: %s\n",
error_message(retval));
}
***************
*** 314,320 ****
{
char sebuf[256];
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket:
%s\n"),
pqStrerror(errno, sebuf, sizeof(sebuf)));
ret = STATUS_ERROR;
--- 311,317 ----
{
char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not restore non-blocking mode on socket:
%s\n"),
pqStrerror(errno, sebuf, sizeof(sebuf)));
ret = STATUS_ERROR;
***************
*** 374,399 ****
* both parts into the string.
*/
static void
! pg_GSS_error(char *mprefix, char *msg, int msglen,
OM_uint32 maj_stat, OM_uint32 min_stat)
{
int mlen;
/* Fetch major error codes */
! pg_GSS_error_int(mprefix, msg, msglen, maj_stat, GSS_C_GSS_CODE);
! mlen = strlen(msg);
/* If there is room left, try to add the minor codes as well */
! if (mlen < msglen-1)
! pg_GSS_error_int(mprefix, msg + mlen, msglen - mlen,
! min_stat, GSS_C_MECH_CODE);
}
/*
* Continue GSS authentication with next token as needed.
*/
static int
! pg_GSS_continue(char *PQerrormsg, PGconn *conn)
{
OM_uint32 maj_stat, min_stat, lmin_s;
--- 371,397 ----
* both parts into the string.
*/
static void
! pg_GSS_error(char *mprefix, PGconn *conn,
OM_uint32 maj_stat, OM_uint32 min_stat)
{
int mlen;
/* Fetch major error codes */
! pg_GSS_error_int(mprefix, conn->errorMessage.data,
! conn->errorMessage.maxlen, maj_stat, GSS_C_GSS_CODE);
! mlen = strlen(conn->errorMessage.data);
/* If there is room left, try to add the minor codes as well */
! if (mlen < conn->errorMessage.maxlen - 1)
! pg_GSS_error_int(mprefix, conn->errorMessage.data + mlen,
! conn->errorMessage.maxlen - mlen, min_stat,
GSS_C_MECH_CODE);
}
/*
* Continue GSS authentication with next token as needed.
*/
static int
! pg_GSS_continue(PGconn *conn)
{
OM_uint32 maj_stat, min_stat, lmin_s;
***************
*** 438,444 ****
if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
{
pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
! PQerrormsg, PQERRORMSG_LENGTH,
maj_stat, min_stat);
gss_release_name(&lmin_s, &conn->gtarg_nam);
if (conn->gctx)
--- 436,442 ----
if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
{
pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
! conn,
maj_stat, min_stat);
gss_release_name(&lmin_s, &conn->gtarg_nam);
if (conn->gctx)
***************
*** 456,462 ****
* Send initial GSS authentication token
*/
static int
! pg_GSS_startup(char *PQerrormsg, PGconn *conn)
{
OM_uint32 maj_stat, min_stat;
int maxlen;
--- 454,460 ----
* Send initial GSS authentication token
*/
static int
! pg_GSS_startup(PGconn *conn)
{
OM_uint32 maj_stat, min_stat;
int maxlen;
***************
*** 464,470 ****
if (conn->gctx)
{
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("duplicate GSS auth request\n"));
return STATUS_ERROR;
}
--- 462,468 ----
if (conn->gctx)
{
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("duplicate GSS auth request\n"));
return STATUS_ERROR;
}
***************
*** 486,492 ****
if (maj_stat != GSS_S_COMPLETE)
{
pg_GSS_error(libpq_gettext("GSSAPI name import error"),
! PQerrormsg, PQERRORMSG_LENGTH,
maj_stat, min_stat);
return STATUS_ERROR;
}
--- 484,490 ----
if (maj_stat != GSS_S_COMPLETE)
{
pg_GSS_error(libpq_gettext("GSSAPI name import error"),
! conn,
maj_stat, min_stat);
return STATUS_ERROR;
}
***************
*** 497,503 ****
*/
conn->gctx = GSS_C_NO_CONTEXT;
! return pg_GSS_continue(PQerrormsg, conn);
}
#endif /* ENABLE_GSS */
--- 495,501 ----
*/
conn->gctx = GSS_C_NO_CONTEXT;
! return pg_GSS_continue(conn);
}
#endif /* ENABLE_GSS */
***************
*** 508,528 ****
*/
static void
! pg_SSPI_error(char *mprefix, char *msg, int msglen, SECURITY_STATUS r)
{
char sysmsg[256];
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, r, 0, sysmsg,
sizeof(sysmsg), NULL) == 0)
! snprintf(msg, msglen, "%s: sspi error %x", mprefix, r);
else
! snprintf(msg, msglen, "%s: %s (%x)", mprefix, sysmsg, r);
}
/*
* Continue SSPI authentication with next token as needed.
*/
static int
! pg_SSPI_continue(char *PQerrormsg, PGconn *conn)
{
SECURITY_STATUS r;
CtxtHandle newContext;
--- 506,526 ----
*/
static void
! pg_SSPI_error(PGconn *conn, char *mprefix, SECURITY_STATUS r)
{
char sysmsg[256];
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, r, 0, sysmsg,
sizeof(sysmsg), NULL) == 0)
! snprintf(conn->errorMessage.data, conn->errorMessage.maxlen,
"%s: sspi error %x", mprefix, r);
else
! snprintf(conn->errorMessage.data, conn->errorMessage.maxlen,
"%s: %s (%x)", mprefix, sysmsg, r);
}
/*
* Continue SSPI authentication with next token as needed.
*/
static int
! pg_SSPI_continue(PGconn *conn)
{
SECURITY_STATUS r;
CtxtHandle newContext;
***************
*** 568,575 ****
if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
{
! pg_SSPI_error(libpq_gettext("SSPI continuation error"),
! PQerrormsg, PQERRORMSG_LENGTH, r);
return STATUS_ERROR;
}
--- 566,572 ----
if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
{
! pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"),
r);
return STATUS_ERROR;
}
***************
*** 580,586 ****
conn->sspictx = malloc(sizeof(CtxtHandle));
if (conn->sspictx == NULL)
{
! strncpy(PQerrormsg, libpq_gettext("out of memory\n"),
PQERRORMSG_LENGTH);
return STATUS_ERROR;
}
memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
--- 577,583 ----
conn->sspictx = malloc(sizeof(CtxtHandle));
if (conn->sspictx == NULL)
{
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
***************
*** 608,614 ****
* This should never happen, at least not for Kerberos
authentication. Keep check
* in case it shows up with other authentication
methods later.
*/
! strncpy(PQerrormsg, "SSPI returned invalid number of
output buffers\n", PQERRORMSG_LENGTH);
return STATUS_ERROR;
}
--- 605,611 ----
* This should never happen, at least not for Kerberos
authentication. Keep check
* in case it shows up with other authentication
methods later.
*/
! printfPQExpBuffer(&conn->errorMessage, "SSPI returned
invalid number of output buffers\n");
return STATUS_ERROR;
}
***************
*** 632,638 ****
* which supports both kerberos and NTLM, but is not compatible with Unix.
*/
static int
! pg_SSPI_startup(char *PQerrormsg, PGconn *conn, int use_negotiate)
{
SECURITY_STATUS r;
TimeStamp expire;
--- 629,635 ----
* which supports both kerberos and NTLM, but is not compatible with Unix.
*/
static int
! pg_SSPI_startup(PGconn *conn, int use_negotiate)
{
SECURITY_STATUS r;
TimeStamp expire;
***************
*** 645,658 ****
conn->sspicred = malloc(sizeof(CredHandle));
if (conn->sspicred == NULL)
{
! strncpy(PQerrormsg, libpq_gettext("out of memory\n"),
PQERRORMSG_LENGTH);
return STATUS_ERROR;
}
r = AcquireCredentialsHandle(NULL,
use_negotiate?"negotiate":"kerberos", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL,
NULL, conn->sspicred, &expire);
if (r != SEC_E_OK)
{
! pg_SSPI_error("acquire credentials failed", PQerrormsg,
PQERRORMSG_LENGTH, r);
free(conn->sspicred);
conn->sspicred = NULL;
return STATUS_ERROR;
--- 642,655 ----
conn->sspicred = malloc(sizeof(CredHandle));
if (conn->sspicred == NULL)
{
! printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of
memory\n"));
return STATUS_ERROR;
}
r = AcquireCredentialsHandle(NULL,
use_negotiate?"negotiate":"kerberos", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL,
NULL, conn->sspicred, &expire);
if (r != SEC_E_OK)
{
! pg_SSPI_error(conn, "acquire credentials failed", r);
free(conn->sspicred);
conn->sspicred = NULL;
return STATUS_ERROR;
***************
*** 665,677 ****
*/
if (conn->pghost == NULL)
{
! strncpy(PQerrormsg, libpq_gettext("hostname must be
specified\n"), PQERRORMSG_LENGTH);
return STATUS_ERROR;
}
conn->sspitarget =
malloc(strlen(conn->krbsrvname)+strlen(conn->pghost)+2);
if (!conn->sspitarget)
{
! strncpy(PQerrormsg, libpq_gettext("out of memory\n"),
PQERRORMSG_LENGTH);
return STATUS_ERROR;
}
sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, conn->pghost);
--- 662,674 ----
*/
if (conn->pghost == NULL)
{
! printfPQExpBuffer(&conn->errorMessage, libpq_gettext("hostname
must be specified\n"));
return STATUS_ERROR;
}
conn->sspitarget =
malloc(strlen(conn->krbsrvname)+strlen(conn->pghost)+2);
if (!conn->sspitarget)
{
! printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of
memory\n"));
return STATUS_ERROR;
}
sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, conn->pghost);
***************
*** 682,688 ****
*/
conn->usesspi = 1;
! return pg_SSPI_continue(PQerrormsg, conn);
}
#endif /* ENABLE_SSPI */
--- 679,685 ----
*/
conn->usesspi = 1;
! return pg_SSPI_continue(conn);
}
#endif /* ENABLE_SSPI */
***************
*** 694,700 ****
* code anyway.
*/
static int
! pg_local_sendauth(char *PQerrormsg, PGconn *conn)
{
#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
--- 691,697 ----
* code anyway.
*/
static int
! pg_local_sendauth(PGconn *conn)
{
#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
***************
*** 736,749 ****
{
char sebuf[256];
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"pg_local_sendauth: sendmsg: %s\n",
pqStrerror(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
#else
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("SCM_CRED authentication method not
supported\n"));
return STATUS_ERROR;
#endif
--- 733,746 ----
{
char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
"pg_local_sendauth: sendmsg: %s\n",
pqStrerror(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
#else
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SCM_CRED authentication method not
supported\n"));
return STATUS_ERROR;
#endif
***************
*** 817,823 ****
*/
int
pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
! const char *password, char *PQerrormsg)
{
#ifndef KRB5
(void) hostname; /* not used */
--- 814,820 ----
*/
int
pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
! const char *password)
{
#ifndef KRB5
(void) hostname; /* not used */
***************
*** 829,852 ****
break;
case AUTH_REQ_KRB4:
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("Kerberos 4 authentication not
supported\n"));
return STATUS_ERROR;
case AUTH_REQ_KRB5:
#ifdef KRB5
pglock_thread();
! if (pg_krb5_sendauth(PQerrormsg, conn->sock,
hostname,
conn->krbsrvname) != STATUS_OK)
{
! /* PQerrormsg already filled in */
pgunlock_thread();
return STATUS_ERROR;
}
pgunlock_thread();
break;
#else
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("Kerberos 5 authentication not
supported\n"));
return STATUS_ERROR;
#endif
--- 826,849 ----
break;
case AUTH_REQ_KRB4:
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Kerberos 4 authentication not
supported\n"));
return STATUS_ERROR;
case AUTH_REQ_KRB5:
#ifdef KRB5
pglock_thread();
! if (pg_krb5_sendauth(conn, conn->sock,
hostname,
conn->krbsrvname) != STATUS_OK)
{
! /* Error message already filled in */
pgunlock_thread();
return STATUS_ERROR;
}
pgunlock_thread();
break;
#else
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Kerberos 5 authentication not
supported\n"));
return STATUS_ERROR;
#endif
***************
*** 865,881 ****
*/
#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
if (conn->gsslib &&
(pg_strcasecmp(conn->gsslib, "gssapi") == 0))
! r = pg_GSS_startup(PQerrormsg, conn);
else
! r = pg_SSPI_startup(PQerrormsg, conn,
0);
#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
! r = pg_GSS_startup(PQerrormsg, conn);
#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
! r = pg_SSPI_startup(PQerrormsg, conn, 0);
#endif
if (r != STATUS_OK)
{
! /* PQerrormsg already filled in. */
pgunlock_thread();
return STATUS_ERROR;
}
--- 862,878 ----
*/
#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
if (conn->gsslib &&
(pg_strcasecmp(conn->gsslib, "gssapi") == 0))
! r = pg_GSS_startup(conn);
else
! r = pg_SSPI_startup(conn, 0);
#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
! r = pg_GSS_startup(conn);
#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
! r = pg_SSPI_startup(conn, 0);
#endif
if (r != STATUS_OK)
{
! /* Error message already filled in. */
pgunlock_thread();
return STATUS_ERROR;
}
***************
*** 889,905 ****
pglock_thread();
#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
if (conn->usesspi)
! r = pg_SSPI_continue(PQerrormsg, conn);
else
! r = pg_GSS_continue(PQerrormsg, conn);
#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
! r = pg_GSS_continue(PQerrormsg, conn);
#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
! r = pg_SSPI_continue(PQerrormsg, conn);
#endif
if (r != STATUS_OK)
{
! /* PQerrormsg already filled in. */
pgunlock_thread();
return STATUS_ERROR;
}
--- 886,902 ----
pglock_thread();
#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
if (conn->usesspi)
! r = pg_SSPI_continue(conn);
else
! r = pg_GSS_continue(conn);
#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
! r = pg_GSS_continue(conn);
#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
! r = pg_SSPI_continue(conn);
#endif
if (r != STATUS_OK)
{
! /* Error message already filled in. */
pgunlock_thread();
return STATUS_ERROR;
}
***************
*** 910,916 ****
#else
case AUTH_REQ_GSS:
case AUTH_REQ_GSS_CONT:
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("GSSAPI authentication
not supported\n"));
return STATUS_ERROR;
#endif
--- 907,913 ----
#else
case AUTH_REQ_GSS:
case AUTH_REQ_GSS_CONT:
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("GSSAPI authentication
not supported\n"));
return STATUS_ERROR;
#endif
***************
*** 923,931 ****
* SSPI negotiation instead of Kerberos.
*/
pglock_thread();
! if (pg_SSPI_startup(PQerrormsg, conn, 1) != STATUS_OK)
{
! /* PQerrormsg already filled in. */
pgunlock_thread();
return STATUS_ERROR;
}
--- 920,928 ----
* SSPI negotiation instead of Kerberos.
*/
pglock_thread();
! if (pg_SSPI_startup(conn, 1) != STATUS_OK)
{
! /* Error message already filled in. */
pgunlock_thread();
return STATUS_ERROR;
}
***************
*** 933,939 ****
break;
#else
case AUTH_REQ_SSPI:
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("SSPI authentication not
supported\n"));
return STATUS_ERROR;
#endif
--- 930,936 ----
break;
#else
case AUTH_REQ_SSPI:
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSPI authentication not
supported\n"));
return STATUS_ERROR;
#endif
***************
*** 944,968 ****
case AUTH_REQ_PASSWORD:
if (password == NULL || *password == '\0')
{
! (void) snprintf(PQerrormsg, PQERRORMSG_LENGTH,
PQnoPasswordSupplied);
return STATUS_ERROR;
}
if (pg_password_sendauth(conn, password, areq) !=
STATUS_OK)
{
! (void) snprintf(PQerrormsg, PQERRORMSG_LENGTH,
"fe_sendauth: error sending password
authentication\n");
return STATUS_ERROR;
}
break;
case AUTH_REQ_SCM_CREDS:
! if (pg_local_sendauth(PQerrormsg, conn) != STATUS_OK)
return STATUS_ERROR;
break;
default:
! snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("authentication method %u not
supported\n"), areq);
return STATUS_ERROR;
}
--- 941,965 ----
case AUTH_REQ_PASSWORD:
if (password == NULL || *password == '\0')
{
! printfPQExpBuffer(&conn->errorMessage,
PQnoPasswordSupplied);
return STATUS_ERROR;
}
if (pg_password_sendauth(conn, password, areq) !=
STATUS_OK)
{
! printfPQExpBuffer(&conn->errorMessage,
"fe_sendauth: error sending password
authentication\n");
return STATUS_ERROR;
}
break;
case AUTH_REQ_SCM_CREDS:
! if (pg_local_sendauth(conn) != STATUS_OK)
return STATUS_ERROR;
break;
default:
! printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("authentication method %u not
supported\n"), areq);
return STATUS_ERROR;
}
***************
*** 975,984 ****
* pg_fe_getauthname -- returns a pointer to dynamic space containing whatever
* name the user has authenticated to the
system
*
! * if there is an error, return NULL with an error message in PQerrormsg
*/
char *
! pg_fe_getauthname(char *PQerrormsg)
{
#ifdef KRB5
char *krb5_name = NULL;
--- 972,981 ----
* pg_fe_getauthname -- returns a pointer to dynamic space containing whatever
* name the user has authenticated to the
system
*
! * if there is an error, return NULL with an error message in pg_conn
*/
char *
! pg_fe_getauthname(PQExpBuffer errorMessage)
{
#ifdef KRB5
char *krb5_name = NULL;
***************
*** 1013,1019 ****
* however, we don't want to free 'name' directly in case it's *not* a
* Kerberos login and we fall through to name = pw->pw_name;
*/
! krb5_name = pg_krb5_authname(PQerrormsg);
name = krb5_name;
#endif
--- 1010,1016 ----
* however, we don't want to free 'name' directly in case it's *not* a
* Kerberos login and we fall through to name = pw->pw_name;
*/
! krb5_name = pg_krb5_authname(errorMessage);
name = krb5_name;
#endif
Index: src/interfaces/libpq/fe-auth.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-auth.h,v
retrieving revision 1.26
diff -c -r1.26 fe-auth.h
*** src/interfaces/libpq/fe-auth.h 5 Jan 2007 22:20:00 -0000 1.26
--- src/interfaces/libpq/fe-auth.h 23 Jul 2007 13:49:02 -0000
***************
*** 19,25 ****
extern int pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char
*hostname,
! const char *password, char *PQerrormsg);
! extern char *pg_fe_getauthname(char *PQerrormsg);
#endif /* FE_AUTH_H */
--- 19,25 ----
extern int pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char
*hostname,
! const char *password);
! extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
#endif /* FE_AUTH_H */
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.350
diff -c -r1.350 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 23 Jul 2007 10:16:54 -0000 1.350
--- src/interfaces/libpq/fe-connect.c 23 Jul 2007 13:56:44 -0000
***************
*** 1723,1734 ****
* avoid the Kerberos code doing a hostname
look-up.
*/
! /*
! * XXX fe-auth.c has not been fixed to support
PQExpBuffers,
! * so:
! */
! if (pg_fe_sendauth(areq, conn, conn->pghost,
conn->pgpass,
!
conn->errorMessage.data) != STATUS_OK)
{
conn->errorMessage.len =
strlen(conn->errorMessage.data);
goto error_return;
--- 1723,1730 ----
* avoid the Kerberos code doing a hostname
look-up.
*/
! if (pg_fe_sendauth(areq, conn, conn->pghost,
conn->pgpass)
! != STATUS_OK)
{
conn->errorMessage.len =
strlen(conn->errorMessage.data);
goto error_return;
***************
*** 3074,3080 ****
char *cp2;
PQconninfoOption *options;
PQconninfoOption *option;
- char errortmp[PQERRORMSG_LENGTH];
/* Make a working copy of PQconninfoOptions */
options = malloc(sizeof(PQconninfoOptions));
--- 3070,3075 ----
***************
*** 3297,3304 ****
*/
if (strcmp(option->keyword, "user") == 0)
{
! option->val = pg_fe_getauthname(errortmp);
! /* note any error message is thrown away */
continue;
}
}
--- 3292,3298 ----
*/
if (strcmp(option->keyword, "user") == 0)
{
! option->val = pg_fe_getauthname(errorMessage);
continue;
}
}
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend