summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/libpq/auth.c165
-rw-r--r--src/backend/libpq/hba.c6
-rw-r--r--src/backend/libpq/pg_hba.conf.sample2
-rw-r--r--src/include/libpq/hba.h5
-rw-r--r--src/include/pg_config.h.in15
5 files changed, 189 insertions, 4 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 4d4e93943e5..60a5c857286 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -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.
*
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 31be6ba33eb..a31f968baab 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -613,6 +613,10 @@ parse_hba_auth(ListCell **line_item, UserAuth *userauth_p,
else if (strcmp(token, "pam") == 0)
*userauth_p = uaPAM;
#endif
+#ifdef USE_LDAP
+ else if (strcmp(token,"ldap") == 0)
+ *userauth_p = uaLDAP;
+#endif
else
{
*error_p = true;
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index 521ce4ef096..abf4e827f13 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -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.
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index 5251db1c054..eaa3cf529ce 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -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;
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index e948cb207ad..16d38f71b8f 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -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