diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/libpq/auth.c | 165 | ||||
-rw-r--r-- | src/backend/libpq/hba.c | 6 | ||||
-rw-r--r-- | src/backend/libpq/pg_hba.conf.sample | 2 | ||||
-rw-r--r-- | src/include/libpq/hba.h | 5 | ||||
-rw-r--r-- | src/include/pg_config.h.in | 15 |
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 |