#include "postgres_fe.h"#include <unistd.h>#include <fcntl.h>#include <sys/param.h>#include <sys/socket.h>#include <netdb.h>#include <pwd.h>#include "libpq-fe.h"#include "fe-auth.h"#include "libpq/md5.h"
Go to the source code of this file.
Functions | |
| static int | pg_local_sendauth (PGconn *conn) |
| static int | pg_password_sendauth (PGconn *conn, const char *password, AuthRequest areq) |
| int | pg_fe_sendauth (AuthRequest areq, PGconn *conn) |
| char * | pg_fe_getauthname (PQExpBuffer errorMessage) |
| char * | PQencryptPassword (const char *passwd, const char *user) |
| char* pg_fe_getauthname | ( | PQExpBuffer | errorMessage | ) |
Definition at line 979 of file fe-auth.c.
References name, pglock_thread, pgunlock_thread, pqGetpwuid(), and username.
Referenced by conninfo_add_defaults().
{
const char *name = NULL;
char *authn;
#ifdef WIN32
char username[128];
DWORD namesize = sizeof(username) - 1;
#else
char pwdbuf[BUFSIZ];
struct passwd pwdstr;
struct passwd *pw = NULL;
#endif
/*
* Some users are using configure --enable-thread-safety-force, so we
* might as well do the locking within our library to protect
* pqGetpwuid(). In fact, application developers can use getpwuid() in
* their application if they use the locking call we provide, or install
* their own locking function using PQregisterThreadLock().
*/
pglock_thread();
if (!name)
{
#ifdef WIN32
if (GetUserName(username, &namesize))
name = username;
#else
if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pw) == 0)
name = pw->pw_name;
#endif
}
authn = name ? strdup(name) : NULL;
pgunlock_thread();
return authn;
}
| int pg_fe_sendauth | ( | AuthRequest | areq, | |
| PGconn * | conn | |||
| ) |
Definition at line 800 of file fe-auth.c.
References AUTH_REQ_CRYPT, AUTH_REQ_GSS, AUTH_REQ_GSS_CONT, AUTH_REQ_KRB4, AUTH_REQ_KRB5, AUTH_REQ_MD5, AUTH_REQ_OK, AUTH_REQ_PASSWORD, AUTH_REQ_SCM_CREDS, AUTH_REQ_SSPI, pg_conn::errorMessage, libpq_gettext, NULL, pg_conn::password_needed, pg_local_sendauth(), pg_password_sendauth(), pg_strcasecmp(), pglock_thread, pg_conn::pgpass, pgunlock_thread, PQnoPasswordSupplied, printfPQExpBuffer(), and STATUS_OK.
Referenced by PQconnectPoll().
{
switch (areq)
{
case AUTH_REQ_OK:
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) != 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
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
case AUTH_REQ_GSS:
#if !defined(ENABLE_SSPI)
/* no native SSPI, so use GSSAPI library for it */
case AUTH_REQ_SSPI:
#endif
{
int r;
pglock_thread();
/*
* If we have both GSS and SSPI support compiled in, use SSPI
* support by default. This is overridable by a connection
* string parameter. Note that when using SSPI we still leave
* the negotiate parameter off, since we want SSPI to use the
* GSSAPI kerberos protocol. For actual SSPI negotiate
* protocol, we use AUTH_REQ_SSPI.
*/
#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;
}
pgunlock_thread();
}
break;
case AUTH_REQ_GSS_CONT:
{
int r;
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;
}
pgunlock_thread();
}
break;
#else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
/* No GSSAPI *or* SSPI support */
case AUTH_REQ_GSS:
case AUTH_REQ_GSS_CONT:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("GSSAPI authentication not supported\n"));
return STATUS_ERROR;
#endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
#ifdef ENABLE_SSPI
case AUTH_REQ_SSPI:
/*
* SSPI has it's own startup message so libpq can decide which
* method to use. Indicate to pg_SSPI_startup that we want 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;
}
pgunlock_thread();
break;
#else
/*
* No SSPI support. However, if we have GSSAPI but not SSPI
* support, AUTH_REQ_SSPI will have been handled in the codepath
* for AUTH_REQ_GSSAPI above, so don't duplicate the case label in
* that case.
*/
#if !defined(ENABLE_GSS)
case AUTH_REQ_SSPI:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSPI authentication not supported\n"));
return STATUS_ERROR;
#endif /* !define(ENABLE_GSSAPI) */
#endif /* ENABLE_SSPI */
case AUTH_REQ_CRYPT:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Crypt authentication not supported\n"));
return STATUS_ERROR;
case AUTH_REQ_MD5:
case AUTH_REQ_PASSWORD:
conn->password_needed = true;
if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
{
printfPQExpBuffer(&conn->errorMessage,
PQnoPasswordSupplied);
return STATUS_ERROR;
}
if (pg_password_sendauth(conn, conn->pgpass, 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;
}
return STATUS_OK;
}
| static int pg_local_sendauth | ( | PGconn * | conn | ) | [static] |
Definition at line 687 of file fe-auth.c.
References buf, pg_conn::errorMessage, libpq_gettext, pqStrerror(), printfPQExpBuffer(), and pg_conn::sock.
Referenced by pg_fe_sendauth().
{
#ifdef HAVE_STRUCT_CMSGCRED
char buf;
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsg;
union
{
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))];
} cmsgbuf;
/*
* The backend doesn't care what we send here, but it wants exactly one
* character to force recvmsg() to block and wait for us.
*/
buf = '\0';
iov.iov_base = &buf;
iov.iov_len = 1;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
/* We must set up a message that will be filled in by kernel */
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDS;
if (sendmsg(conn->sock, &msg, 0) == -1)
{
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
}
| static int pg_password_sendauth | ( | PGconn * | conn, | |
| const char * | password, | |||
| AuthRequest | areq | |||
| ) | [static] |
Definition at line 739 of file fe-auth.c.
References AUTH_REQ_MD5, AUTH_REQ_PASSWORD, pg_conn::errorMessage, free, libpq_gettext, malloc, MD5_PASSWD_LEN, pg_conn::md5Salt, pg_md5_encrypt(), PG_PROTOCOL_MAJOR, pg_conn::pguser, pqPacketSend(), printfPQExpBuffer(), and pg_conn::pversion.
Referenced by pg_fe_sendauth().
{
int ret;
char *crypt_pwd = NULL;
const char *pwd_to_send;
/* Encrypt the password if needed. */
switch (areq)
{
case AUTH_REQ_MD5:
{
char *crypt_pwd2;
/* Allocate enough space for two MD5 hashes */
crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
if (!crypt_pwd)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1;
if (!pg_md5_encrypt(password, conn->pguser,
strlen(conn->pguser), crypt_pwd2))
{
free(crypt_pwd);
return STATUS_ERROR;
}
if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), conn->md5Salt,
sizeof(conn->md5Salt), crypt_pwd))
{
free(crypt_pwd);
return STATUS_ERROR;
}
pwd_to_send = crypt_pwd;
break;
}
case AUTH_REQ_PASSWORD:
pwd_to_send = password;
break;
default:
return STATUS_ERROR;
}
/* Packet has a message type as of protocol 3.0 */
if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
ret = pqPacketSend(conn, 'p', pwd_to_send, strlen(pwd_to_send) + 1);
else
ret = pqPacketSend(conn, 0, pwd_to_send, strlen(pwd_to_send) + 1);
if (crypt_pwd)
free(crypt_pwd);
return ret;
}
| char* PQencryptPassword | ( | const char * | passwd, | |
| const char * | user | |||
| ) |
Definition at line 1040 of file fe-auth.c.
References free, malloc, MD5_PASSWD_LEN, and pg_md5_encrypt().
Referenced by exec_command(), and main().
{
char *crypt_pwd;
crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
if (!crypt_pwd)
return NULL;
if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
{
free(crypt_pwd);
return NULL;
}
return crypt_pwd;
}
1.7.1