Commit 357cc01e authored by Bruce Momjian's avatar Bruce Momjian

This patch adds native LDAP auth, for those platforms that don't have

PAM (such as Win32, but also unixen without PAM). On Unix, uses
OpenLDAP. On win32, uses the builin WinLDAP library.

Magnus Hagander
parent ebdc3582
This diff is collapsed.
dnl Process this file with autoconf to produce a configure script.
dnl $PostgreSQL: pgsql/configure.in,v 1.454 2006/03/05 15:58:18 momjian Exp $
dnl $PostgreSQL: pgsql/configure.in,v 1.455 2006/03/06 17:41:43 momjian Exp $
dnl
dnl Developers, please strive to achieve this order:
dnl
......@@ -444,6 +444,17 @@ AC_MSG_RESULT([$with_pam])
AC_SUBST(with_pam)
#
# LDAP
#
AC_MSG_CHECKING([whether to build with LDAP support])
PGAC_ARG_BOOL(with, ldap, no,
[ --with-ldap build with LDAP support],
[AC_DEFINE([USE_LDAP], 1, [Define to 1 to build with LDAP support. (--with-ldap)])])
AC_MSG_RESULT([$with_ldap])
AC_SUBST(with_ldap)
#
# Bonjour
#
......@@ -669,6 +680,14 @@ if test "$with_pam" = yes ; then
fi
if test "$with_ldap" = yes ; then
if test "$PORTNAME" != "win32"; then
AC_CHECK_LIB(ldap, ldap_bind, [], [AC_MSG_ERROR([library 'ldap' is required for LDAP])])
else
AC_CHECK_LIB(wldap32, ldap_bind, [], [AC_MSG_ERROR([library 'wldap32' is required for LDAP])])
fi
fi
##
## Header files
##
......@@ -744,6 +763,19 @@ if test "$with_pam" = yes ; then
[AC_MSG_ERROR([header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.])])])
fi
if test "$with_ldap" = yes ; then
if test "$PORTNAME" != "win32"; then
AC_CHECK_HEADERS(ldap.h, [],
[AC_MSG_ERROR([header file <ldap.h> is required for LDAP])])
else
AC_CHECK_HEADERS(winldap.h, [],
[AC_MSG_ERROR([header file <winldap.h> is required for LDAP])],
[AC_INCLUDES_DEFAULT
#include <windows.h>
])
fi
fi
if test "$with_bonjour" = yes ; then
AC_CHECK_HEADER(DNSServiceDiscovery/DNSServiceDiscovery.h, [], [AC_MSG_ERROR([header file <DNSServiceDiscovery/DNSServiceDiscovery.h> is required for Bonjour])])
fi
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.134 2006/03/05 15:58:27 momjian Exp $
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.135 2006/03/06 17:41:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -69,6 +69,32 @@ static Port *pam_port_cludge; /* Workaround for passing "Port *port" into
* pam_passwd_conv_proc */
#endif /* USE_PAM */
#ifdef USE_LDAP
#ifndef WIN32
/* We use a deprecated function to keep the codepaths the same as the
* win32 one. */
#define LDAP_DEPRECATED 1
#include <ldap.h>
#else
/* Header broken in MingW */
#define ldap_start_tls_sA __BROKEN_LDAP_HEADER
#include <winldap.h>
#undef ldap_start_tls_sA
/* Correct header from the Platform SDK */
WINLDAPAPI ULONG ldap_start_tls_sA (
IN PLDAP ExternalHandle,
OUT PULONG ServerReturnValue,
OUT LDAPMessage **result,
IN PLDAPControlA *ServerControls,
IN PLDAPControlA *ClientControls
);
#endif
static int CheckLDAPAuth(Port *port);
#endif
#ifdef KRB5
/*----------------------------------------------------------------
* MIT Kerberos authentication system - protocol version 5
......@@ -327,6 +353,11 @@ auth_failed(Port *port, int status)
errstr = gettext_noop("PAM authentication failed for user \"%s\"");
break;
#endif /* USE_PAM */
#ifdef USE_LDAP
case uaLDAP:
errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
break;
#endif /* USE_LDAP */
default:
errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
break;
......@@ -455,6 +486,12 @@ ClientAuthentication(Port *port)
break;
#endif /* USE_PAM */
#ifdef USE_LDAP
case uaLDAP:
status = CheckLDAPAuth(port);
break;
#endif
case uaTrust:
status = STATUS_OK;
break;
......@@ -674,6 +711,132 @@ CheckPAMAuth(Port *port, char *user, char *password)
#endif /* USE_PAM */
#ifdef USE_LDAP
static int
CheckLDAPAuth(Port *port)
{
char *passwd;
char server[128];
char basedn[128];
char prefix[128];
char suffix[128];
LDAP *ldap;
int ssl = 0;
int r;
int ldapversion = LDAP_VERSION3;
int ldapport = LDAP_PORT;
char fulluser[128];
if (!port->auth_arg || port->auth_arg[0] == '\0')
{
ereport(LOG,
(errmsg("LDAP configuration URL not specified")));
return STATUS_ERROR;
}
/*
* Crack the LDAP url. We do a very trivial parse..
* ldap[s]://<server>[:<port>]/<basedn>[;prefix[;suffix]]
*/
server[0] = '\0';
basedn[0] = '\0';
prefix[0] = '\0';
suffix[0] = '\0';
/* ldap, including port number */
r = sscanf(port->auth_arg,
"ldap://%127[^:]:%i/%127[^;];%127[^;];%127s",
server, &ldapport, basedn, prefix, suffix);
if (r < 3)
{
/* ldaps, including port number */
r = sscanf(port->auth_arg,
"ldaps://%127[^:]:%i/%127[^;];%127[^;];%127s",
server, &ldapport, basedn, prefix, suffix);
if (r >=3) ssl = 1;
}
if (r < 3)
{
/* ldap, no port number */
r = sscanf(port->auth_arg,
"ldap://%127[^/]/%127[^;];%127[^;];%127s",
server, basedn, prefix, suffix);
}
if (r < 2)
{
/* ldaps, no port number */
r = sscanf(port->auth_arg,
"ldaps://%127[^/]/%127[^;];%127[^;];%127s",
server, basedn, prefix, suffix);
if (r >= 2) ssl = 1;
}
if (r < 2)
{
ereport(LOG,
(errmsg("Invalid LDAP url: '%s'", port->auth_arg)));
return STATUS_ERROR;
}
sendAuthRequest(port, AUTH_REQ_PASSWORD);
passwd = recv_password_packet(port);
if (passwd == NULL)
return STATUS_EOF; /* client wouldn't send password */
ldap = ldap_init(server, ldapport);
if (!ldap)
{
ereport(LOG,
(errmsg("Failed to initialize LDAP: %i",
#ifndef WIN32
errno
#else
(int)LdapGetLastError()
#endif
)));
return STATUS_ERROR;
}
if ((r = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
{
ereport(LOG,
(errmsg("Failed to set LDAP version: %i", r)));
return STATUS_ERROR;
}
if (ssl)
{
#ifndef WIN32
if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
#else
if ((r = ldap_start_tls_sA(ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
#endif
{
ereport(LOG,
(errmsg("Failed to start LDAP TLS session: %i", r)));
return STATUS_ERROR;
}
}
snprintf(fulluser, sizeof(fulluser)-1, "%s%s%s", prefix, port->user_name, suffix);
fulluser[sizeof(fulluser)-1] = '\0';
r = ldap_simple_bind_s(ldap, fulluser, passwd);
ldap_unbind(ldap);
if (r != LDAP_SUCCESS)
{
ereport(LOG,
(errmsg("LDAP login failed for user '%s' on server '%s': %i",fulluser,server,r)));
return STATUS_ERROR;
}
return STATUS_OK;
}
#endif /* USE_LDAP */
/*
* Collect password response packet from frontend.
*
......
......@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.150 2006/03/05 15:58:27 momjian Exp $
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.151 2006/03/06 17:41:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -612,6 +612,10 @@ parse_hba_auth(ListCell **line_item, UserAuth *userauth_p,
#ifdef USE_PAM
else if (strcmp(token, "pam") == 0)
*userauth_p = uaPAM;
#endif
#ifdef USE_LDAP
else if (strcmp(token,"ldap") == 0)
*userauth_p = uaLDAP;
#endif
else
{
......
......@@ -35,7 +35,7 @@
# an IP address and netmask in separate columns to specify the set of hosts.
#
# METHOD can be "trust", "reject", "md5", "crypt", "password",
# "krb5", "ident", or "pam". Note that "password" sends passwords
# "krb5", "ident", "pam" or "ldap". Note that "password" sends passwords
# in clear text; "md5" is preferred since it sends encrypted passwords.
#
# OPTION is the ident map or the name of the PAM service, depending on METHOD.
......
......@@ -4,7 +4,7 @@
* Interface to hba.c
*
*
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.41 2005/10/15 02:49:44 momjian Exp $
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.42 2006/03/06 17:41:44 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -26,6 +26,9 @@ typedef enum UserAuth
#ifdef USE_PAM
,uaPAM
#endif /* USE_PAM */
#ifdef USE_LDAP
,uaLDAP
#endif
} UserAuth;
typedef struct Port hbaPort;
......
......@@ -204,12 +204,18 @@
/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the <ldap.h> header file. */
#undef HAVE_LDAP_H
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#undef HAVE_LIBCRYPTO
/* Define to 1 if you have the `eay32' library (-leay32). */
#undef HAVE_LIBEAY32
/* Define to 1 if you have the `ldap' library (-lldap). */
#undef HAVE_LIBLDAP
/* Define to 1 if you have the `pam' library (-lpam). */
#undef HAVE_LIBPAM
......@@ -222,6 +228,9 @@
/* Define to 1 if you have the `ssleay32' library (-lssleay32). */
#undef HAVE_LIBSSLEAY32
/* Define to 1 if you have the `wldap32' library (-lwldap32). */
#undef HAVE_LIBWLDAP32
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
......@@ -513,6 +522,9 @@
/* Define to 1 if you have the <wctype.h> header file. */
#undef HAVE_WCTYPE_H
/* Define to 1 if you have the <winldap.h> header file. */
#undef HAVE_WINLDAP_H
/* Define to the appropriate snprintf format for 64-bit ints, if any. */
#undef INT64_FORMAT
......@@ -589,6 +601,9 @@
(--enable-integer-datetimes) */
#undef USE_INTEGER_DATETIMES
/* Define to 1 to build with LDAP support. (--with-ldap) */
#undef USE_LDAP
/* Define to select named POSIX semaphores. */
#undef USE_NAMED_POSIX_SEMAPHORES
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment