/* Copyright © 1998, 1999 Enbridge Pipelines Inc. Copyright © 1999-2006 Dave Carrigan All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Apache itself. This module is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The copyright holder of this module can not be held liable for any general, special, incidental or consequential damages arising out of the use of the module. $Id: auth_ldap.h,v 1.15 2001/04/07 20:20:17 dave Exp $ */ #ifdef __AUTH_LDAP_C__ #define EXTERN #else #define EXTERN extern #endif #include #include #include #include #include #include #include #include #include #include #ifndef LDAP_SDK_VERSION #if defined(WITH_OPENLDAP) && LDAP_VENDOR_VERSION < 20000 #define LDAP_SDK_VERSION 2 #else #define LDAP_SDK_VERSION 3 #endif #endif #if defined(WITH_OPENLDAP) && LDAP_SDK_VERSION > 2 #define HAVE_TLS #endif #if defined(WITH_SHARED_LDAP_CACHE) && !defined(EAPI) #undef WITH_SHARED_LDAP_CACHE #endif #ifdef WITH_SSL #include #endif #include #include #include #include "auth_ldap_cache_mgr.h" /* Backwards compatibility for Apache 1.2 */ #if APACHE_RELEASE < 1030000 #define auth_ldap_get_pw get_pw #define ap_pcalloc pcalloc #define ap_pstrdup pstrdup #define ap_get_module_config get_module_config #define ap_get_basic_auth_pw get_basic_auth_pw #define ap_set_string_slot set_string_slot #define ap_set_flag_slot set_flag_slot #define ap_getword getword #define ap_note_basic_auth_failure note_basic_auth_failure #define ap_requires requires #define ap_getword_conf getword_conf #define APLOG_MARK __FILE__,__LINE__ #define APLOG_DEBUG 7 #define APLOG_WARNING 4 #define APLOG_ERR 3 #define APLOG_NOERRNO 0 #endif #ifndef WIN32 #define ALD_MM_FILE_MODE ( S_IRUSR|S_IWUSR ) #else #define ALD_MM_FILE_MODE ( _S_IREAD|_S_IWRITE ) #endif /* * Maintain a cache of LDAP URLs that the server handles. Each node in * the cache contains the search cache for that URL, and a compare cache * for the URL. The compare cash is populated when doing require group * compares. */ typedef struct url_node { char *url; ald_cache *search_cache; ald_cache *compare_cache; ald_cache *dn_compare_cache; } url_node; /* * We cache every successful search and bind operation, using the username * as the key. Each node in the cache contains the returned DN, plus the * password used to bind. */ typedef struct search_node { char *username; /* Cache key */ char *dn; /* DN returned from search */ char *bindpw; /* The most recently used bind password; NULL if the bind failed */ time_t lastbind; /* Time of last successful bind */ } search_node; /* * We cache every successful compare operation, using the DN, attrib, and * value as the key. */ typedef struct compare_node { char *dn; /* DN, attrib and value combine to be the key */ char *attrib; char *value; time_t lastcompare; } compare_node; /* * We cache every successful compare dn operation, using the dn in the require * statement and the dn fetched based on the client-provided username. */ typedef struct dn_compare_node { char *reqdn; /* The DN in the require dn statement */ char *dn; /* The DN found in the search */ } dn_compare_node; #if LDAP_SDK_VERSION <= 2 int ldap_search_ext_s(LDAP *ldap, char *base, int scope, char *filter, char **attrs, int attrsonly, void *servertrls, void *clientctrls, void *timeout, int sizelimit, LDAPMessage **res); void ldap_memfree(void *p); /* The const_cast is used to get around the fact that some of the LDAPv2 prototypes have non-const parameters, while the same ones in LDAPv3 are const. If compiling with LDAPv2, the const_cast casts away the constness, but won't under LDAPv3 */ #define const_cast(x) ((char *)(x)) #else #define const_cast(x) (x) #endif /* LDAP_SDK_VERSION */ /* * We want the ldap connections to be long-lived; we'll need one * connection for each host/port combination. We keep these in a * global linked list, so they're around for as long as the apache * process is around. * * Note that the URLs ldap://ldap and ldap://ldap.airius.com should * represent the same connection, but will result in different * connections entries in the cache. Caveat emptor. */ /* * Values in this enum help us keep track of how this connection is * currently bound to the server */ typedef enum { bind_none, /* Not bound */ bind_system, /* Bound using config bind creds */ bind_user /* Bound using user-supplied creds */ } bindings; /* Define some errors that are mysteriously gone from OpenLDAP 2.x */ #ifndef LDAP_URL_ERR_NOTLDAP #if defined(WITH_OPENLDAP) && LDAP_VENDOR_VERSION >= 20000 #define LDAP_URL_ERR_NOTLDAP LDAP_URL_ERR_BADSCHEME #endif #endif #ifndef LDAP_URL_ERR_NODN #if defined(WITH_OPENLDAP) && LDAP_VENDOR_VERSION >= 20000 #define LDAP_URL_ERR_NODN LDAP_URL_ERR_BADURL #endif #endif struct LDAPconnection { LDAP *ldap; mutex *mtx; char *bounddn; char *host; int port; bindings boundas; #ifdef HAVE_TLS int withtls; #endif struct LDAPconnection *next; }; /* auth_ldap global configuration */ typedef struct { long search_cache_ttl; /* TTL for search cache */ long search_cache_size; /* Size of search cache */ long compare_cache_ttl; /* TTL for compare cache */ long compare_cache_size; /* Size of compare cache */ mutex *mtx; struct LDAPconnection *ldapconnections; #ifdef WITH_SSL int have_certdb; #endif } auth_ldap_server_conf; #define GROUPATTR_MAX_ELTS 10 /* Values that the deref member can have */ typedef enum { never=LDAP_DEREF_NEVER, searching=LDAP_DEREF_SEARCHING, finding=LDAP_DEREF_FINDING, always=LDAP_DEREF_ALWAYS } deref_options; /* The actual LDAP auth struct. */ typedef struct { int auth_authoritative; /* Is this auth method the one and only? */ int enabled; /* Is auth_ldap enabled in this directory? */ int version; /* LDAP version to use */ /* These parameters are all derived from the AuthLDAPURL directive */ char *url; /* String representation of the URL */ char *host; /* Name of the LDAP server (or space separated list) */ int port; /* Port of the LDAP server */ char *basedn; /* Base DN to do all searches from */ char *attribute; /* Attribute to search for */ int scope; /* Scope of the search */ char *filter; /* Filter to further limit the search */ deref_options deref; /* how to handle alias dereferening */ #ifdef AUTH_LDAP_FRONTPAGE_HACK int frontpage_hack; /* Hack for frontpage support */ #endif char *binddn; /* DN to bind to server (can be NULL) */ char *bindpw; /* Password to bind to server (can be NULL) */ char *dn; /* The saved dn from a successful search */ char *user; /* The username provided by the client */ int user_is_dn; /* If true, connection->user is DN instead of userid */ int compare_dn_on_server; /* If true, will use server to do DN compare */ int have_ldap_url; /* Set if we have found an LDAP url */ array_header *groupattr; /* List of Group attributes */ int group_attrib_is_dn; /* If true, the group attribute is the DN, otherwise, it's the exact string passed by the HTTP client */ struct LDAPconnection *ldc; /* Pointer to an LDAP connection in the linked list */ #ifdef WITH_SSL int secure; /* True if use SSL connection */ #endif #ifdef HAVE_TLS int starttls; /* True if StartTLS */ #endif } auth_ldap_config_rec; struct groupattr_entry { char *name; }; /* On NT, ap_release_mutex returns the result of ReleaseMutex. On Unix, ap_release_mutex is a macro that evaluates to MULTI_OK (0). However, a successful result of ReleaseMutex is not MULTI_OK. Thus, we can't do if (ap_release_mutex(m) != MULTI_OK) { ... warn ... } because it will do exactly the opposite of what we want. However, if we do ap_release_mutex(m); then we get a bunch of ugly errors about 'statement with no effect' under Unix. So, I define my own release_mutex function. */ #ifdef MULTITHREAD #define GETMUTEX(mtx) \ if (ap_acquire_mutex(mtx) != MULTI_OK) \ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r, \ "Could not acquire connection mutex. Expect deadlocks.") #define RELMUTEX(m) ap_release_mutex(m) #else #define GETMUTEX(mtx) #define RELMUTEX(m) #endif #ifdef WITH_SHARED_LDAP_CACHE EXTERN AP_MM *auth_ldap_mm; #endif EXTERN ald_cache *auth_ldap_cache; extern void auth_ldap_init_module(server_rec *s, pool *p); extern void *create_auth_ldap_dir_config(pool *p, char *d); extern const char *parse_auth_ldap_version(cmd_parms *cmd, auth_ldap_config_rec *sec, char *version); extern const char *parse_auth_ldap_url(cmd_parms *cmd, auth_ldap_config_rec *sec, char *url); extern const char *auth_ldap_add_group_attribute(cmd_parms *cmd, auth_ldap_config_rec *sec, char *arg); extern const char *auth_ldap_set_cache_ttl(cmd_parms *cmd, void *dummy, char *ttl); extern const char *auth_ldap_set_cache_size(cmd_parms *cmd, void *dummy, char *size); extern const char *auth_ldap_set_opcache_ttl(cmd_parms *cmd, void *dummy, char *size); extern const char *auth_ldap_set_opcache_size(cmd_parms *cmd, void *dummy, char *size); extern const char *auth_ldap_set_compare_flag(cmd_parms *cmd, void *dummy, char *size); #ifdef WITH_SSL extern const char *auth_ldap_set_certdbpath(cmd_parms *cmd, void *dummy, char *path); #endif extern const char *auth_ldap_add_redundant(cmd_parms *cmd, auth_ldap_config_rec *sec, char *f); extern const char *auth_ldap_set_deref(cmd_parms *cmd, auth_ldap_config_rec *sec, char *f); extern void *create_auth_ldap_config(pool *p, server_rec *s); extern int auth_ldap_display_info(request_rec *r); extern const char *auth_ldap_version; int auth_ldap_authbind(const char *, request_rec *, url_node *); int auth_ldap_comparedn(const char *, const char *, request_rec *, url_node *); int auth_ldap_compare(const char *, const char *, const char *, request_rec *, ald_cache *); int auth_ldap_connect_to_server(request_rec *r); void auth_ldap_free_connection(request_rec *r, int log); void auth_ldap_log_reason(request_rec *r, const char *fmt, ...); unsigned long auth_ldap_search_node_hash(void *); int auth_ldap_search_node_compare(void *, void *); void * auth_ldap_search_node_copy(void *); void auth_ldap_search_node_free(void *); unsigned long auth_ldap_compare_node_hash(void *); int auth_ldap_compare_node_compare(void *, void *); void * auth_ldap_compare_node_copy(void *); void auth_ldap_compare_node_free(void *); unsigned long auth_ldap_group_compare_node_hash(void *); int auth_ldap_group_compare_node_compare(void *, void *); void * auth_ldap_group_compare_node_copy(void *); void auth_ldap_group_compare_node_free(void *); unsigned long auth_ldap_dn_compare_node_hash(void *); int auth_ldap_dn_compare_node_compare(void *, void *); void * auth_ldap_dn_compare_node_copy(void *); void auth_ldap_dn_compare_node_free(void *); unsigned long auth_ldap_url_node_hash(void *n); int auth_ldap_url_node_compare(void *a, void *b); void * auth_ldap_url_node_copy(void *c); void auth_ldap_url_node_free(void *n);