Skip to content

Instantly share code, notes, and snippets.

@sonatard
Created July 16, 2016 07:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sonatard/daab507ddafbbe3cd61c9d9edf876b8d to your computer and use it in GitHub Desktop.
Save sonatard/daab507ddafbbe3cd61c9d9edf876b8d to your computer and use it in GitHub Desktop.
/*
* ====================================================================
* Copyright (c) 1995-2000 Lyonel VINCENT and Jeff Morrow.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 5. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* mod_ldap.c: LDAP-based access checking for Apache
*
* Lyonel VINCENT (vincent@trotek.ec-lyon.fr) and Jeff Morrow
* (jmorrow@alum.mit.edu)
* changes by Sam Alcoff (alcoff@survival.net) to compile with
* Apache 1.3
* changes by Rick Perry (perry@ece.vill.edu): bugs fixes and code
* cleanups.
*
* Other contributors:
* Markku.Jarvinen@tpo.fi
* Soren.Roug@EEA.eu.int
* Dan Rich (drich@solipsa.com)
* Martin Mansfield (Martin.Mansfield@lombardrisk.com)
* Jamie Scuglia <jamie@cs.monash.edu.au>
*
* Version 1.8 (May 2000) -- small bug fix courtesy of Martin
* Mansfield to ensure that any whitespace characters can be used
* as field separators in the config file. Another bug fix by
* Jamie Scuglia ensures proper behavior when LDAPAuth is set to
* "off". Another fix by me (Jeff Morrow) to ensure that
* resetUsername doesn't hang when presented with a DN without a
* comma (just in case).
* Version 1.7 (Jan 2000) -- fixed the resetUsername function to
* return the attribute defined in LDAPuseridAttr rather than the
* attribute that makes up the first part of the DN. Bug pointed
* out by Dan Rich (drich@solipsa.com).
* Version 1.6 (July 1999) -- a few feature additions and bug fixes
* (including a seg fault fix) by Markku Jarvinen and Soren Roug.
* Also compiles warning-free on Linux/gcc.
* Version 1.5 (Jan 1999) -- adds several new features and merges
* the functionality of mod_ldap 1.4 with mod_auth_ldap 1.1.
*
* based on the mod_auth_ldap.c module written by
* Norman RICHARDS (orb@cs.utexas.edu)
*
* KNOWN BUG:
*
* The function resetUsername may fail if your LDAP schema builds
* its DN's out of multiple attributes, such as
* "cn=Jeff Morrow,uid=jmorrow,o=www.kie.berkeley.edu,c=us".
*
* =============================================
*
* For more information on LDAP, see the LDAPWorld web
* page at: http://www.critical-angle.com/ldapworld/
*
* =============================================
*
* The goal of this module is to allow access checking
* through user information stored in an LDAP directory.
*
* This module works very similarly to other access checking
* modules.
*
* To use the module, you need to add this file to your
* apache src directory. Add the following line to your
* Configuration file:
*
* Module ldap_module mod_ldap.o
*
* Alternatively, if you have placed mod_ldap.c in the directory
* src/modules/extra, you may add the following flag to your
* configure directive:
*
* --activate-module=src/modules/extra/mod_ldap.o
*
* In either case, you will also need to add the appropriate
* locations for your ldap/lber libraries and includes to
* EXTRA_LIBS and EXTRA_INCLUDES.
*
* =============================================
*
* The following directives can be used in your access.conf
* file in the same way as you would configure the standard
* authentication modules.
*
* LDAPAuth <flag>
*
* LDAPServer <LDAP URL>
*
* This sets the LDAP server to be used. The ldap url
* is of the form "ldap://yourhost.com:portnumber/"
*
* LDAPBindName <Distinguished Name>
* LDAPBindPass <password>
*
* If the module needs to authenticate itself, enter the user
* name and password here.
*
* LDAPBase <Base DN>
*
* Specifies the base DN for all LDAP searches.
*
* LDAPuseridAttr <attribute name>
* LDAPpasswordAttr <attribute name>
*
* Specifies the attribute names that should be compared with
* the supplied username and password, respectively.
*
* NOTE: if your LDAP server contains encrypted passwords, this
* module will only work if the LDAPpasswordAttr config line is
* omitted.
*
* Default for LDAPuseridAttr is "userid".
*
* LDAPgroupMemberAttr <attribute name>
*
* Specifies the attribute name that your LDAP server uses to
* store the individual members of a group. Default is
* "uniquemember", which is used by Netscape's Directory Server.
*
* LDAPSearchMode <mode>
*
* Specifies the scope to be used for LDAP searches. Can
* be "base", "onelevel" (default), or "subtree". Mode "compare",
* equivalent to "base", is allowed for backward compatibility.
* See LDAP documentation for more info.
*
* LDAPUseDNForRemoteUser <flag>
*
* Defaults to "off". If set to "on", this module will reset the
* identity of the remote user from the username provided by the
* user to the user's full distinguished name.
*
* The require directives are as follows:
*
* require filter <LDAP search filter>
*
* The search filter is in LDAP standard format as specified by
* RFC1960
*
* require valid-user
*
* Allows any valid LDAP user.
*
* require user <user DN or username>
*
* Allows the specified user. May take a DN in the form of
* "uid=jeffm,o=www.kie.berkeley.edu" or a base username like
* "jeffm".
*
* require group <group DN>
*
* Allows access to anyone in the given group. The group members
* must be defined in the attribute specified by the LDAPgroupMemberAttr
* field. Note that the group name must be a full DN.
*
* =============================================
*
* examples:
*
* LDAPServer ldap://x500.hp.com/
* require filter (|(&(ou=ENSD)(l=Grenoble))(ou=HP Labs))
*
* require user "cn=Jeff Morrow,o=www.kie.berkeley.edu"
* require user "Jeff Morrow"
*
* require group "cn=teachers,o=www.kie.berkeley.edu"
*
*/
#include "ap_compat.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "lber.h"
#include "ldap.h"
module ldap_module;
/* --------------------------------- */
typedef struct {
char *host;
int port;
char *base;
char *bindname;
int searchmode;
char *bindpass;
int ldap_auth;
int reset_username;
char *userid_attr;
char *userpassword_attr;
char *groupmember_attr;
LDAP *ld;
} ldap_config_struct;
void resetUsername(char* username, ldap_config_struct* conf, request_rec* r);
void *create_ldap_dir_config(pool *p, char *d) {
ldap_config_struct *conf;
conf = (ldap_config_struct *) ap_pcalloc(p, sizeof(ldap_config_struct));
conf->host = "localhost";
conf->port = LDAP_PORT;
conf->base = NULL;
conf->searchmode = LDAP_SCOPE_ONELEVEL;
conf->bindname = NULL;
conf->bindpass = NULL;
conf->userid_attr = "userid";
conf->userpassword_attr = NULL;
conf->groupmember_attr = "uniquemember";
conf->ldap_auth = 0;
conf->reset_username = 1;
conf->ld = NULL;
return conf;
}
/* --------------------------------- */
const char *set_reset_username(cmd_parms *cmd, ldap_config_struct *conf, int arg)
{
conf->reset_username = arg ? 0 : 1;
return NULL;
}
const char *set_ldap_auth(cmd_parms *cmd, ldap_config_struct *conf, int arg)
{
conf->ldap_auth = arg;
return NULL;
}
const char *set_ldap_base(cmd_parms *cmd, ldap_config_struct *conf, char *base)
{
conf->base=ap_pstrdup(cmd->pool, base);
return NULL;
}
const char *set_ldap_useridattr(cmd_parms *cmd, ldap_config_struct *conf, char *attr)
{
conf->userid_attr=ap_pstrdup(cmd->pool, attr);
return NULL;
}
const char *set_ldap_passwordattr(cmd_parms *cmd, ldap_config_struct *conf, char *attr)
{
conf->userpassword_attr=ap_pstrdup(cmd->pool, attr);
return NULL;
}
/* User-configurable group member attribute added JM 1/12/99 */
const char *set_ldap_groupmemberattr(cmd_parms *cmd, ldap_config_struct *conf, char *attr)
{
conf->groupmember_attr=ap_pstrdup(cmd->pool, attr);
return NULL;
}
const char *set_ldap_server(cmd_parms *cmd, ldap_config_struct *conf, char *url) {
LDAPURLDesc *ldap_url;
if (!ldap_is_ldap_url(url)) {
return "server is not a properly formatted LDAP url";
}
if (ldap_url_parse(url,&ldap_url)!=0) {
return "cannot parse LDAP url";
}
conf->host=ap_pstrdup(cmd->pool, ldap_url->lud_host);
if (ldap_url->lud_port!=0)
conf->port=ldap_url->lud_port;
ldap_free_urldesc(ldap_url);
return NULL;
}
const char *set_ldap_bindname(cmd_parms *cmd, ldap_config_struct *conf, char *name) {
conf->bindname = ap_pstrdup(cmd->pool,name);
return NULL;
}
const char *set_ldap_bindpass(cmd_parms *cmd, ldap_config_struct *conf, char *pass) {
conf->bindpass = ap_pstrdup(cmd->pool,pass);
return NULL;
}
/* Changed by Soren Roug to allow search mode "base" and to use LDAP's own constants
for each mode. Added 7/14/99 */
const char *set_ldap_searchmode(cmd_parms *cmd, ldap_config_struct *conf, char *mode) {
if (strcmp(mode,"compare")==0) {
conf->searchmode=LDAP_SCOPE_BASE;
} else if (strcmp(mode,"base")==0) {
conf->searchmode=LDAP_SCOPE_BASE;
} else if (strcmp(mode,"onelevel")==0) {
conf->searchmode=LDAP_SCOPE_ONELEVEL;
} else if (strcmp(mode,"subtree")==0) {
conf->searchmode=LDAP_SCOPE_SUBTREE;
}
return NULL;
}
command_rec ldap_auth_cmds[] = {
{ "LDAPAuth", set_ldap_auth, NULL, OR_AUTHCFG, FLAG, "Activate LDAP auth" },
{ "LDAPUseDNForRemoteUser", set_reset_username, NULL, OR_AUTHCFG, FLAG, "Use DN instead of simple username" },
{ "LDAPServer", set_ldap_server, NULL, OR_AUTHCFG, TAKE1, "LDAP URL" },
{ "LDAPBase", set_ldap_base, NULL, OR_AUTHCFG, TAKE1, "LDAP search base" },
{ "LDAPuseridAttr", set_ldap_useridattr, NULL, OR_AUTHCFG, TAKE1, "LDAP user id attribute name" },
{ "LDAPpasswordAttr", set_ldap_passwordattr, NULL, OR_AUTHCFG, TAKE1, "LDAP user password attribute name" },
{ "LDAPgroupMemberAttr", set_ldap_groupmemberattr, NULL, OR_AUTHCFG, TAKE1, "LDAP group member attribute name" },
{ "LDAPBindName", set_ldap_bindname, NULL, OR_AUTHCFG, RAW_ARGS, NULL },
{ "LDAPBindPass", set_ldap_bindpass, NULL, OR_AUTHCFG, RAW_ARGS, NULL },
{ "LDAPSearchMode", set_ldap_searchmode, NULL, OR_AUTHCFG, TAKE1, NULL },
{NULL}
};
/* --------------------------------- */
static LDAP *ldap_open_and_bind (char *host,int port,char *username,char *password) {
LDAP *ld;
int res;
ld=ldap_open(host,port);
if (!ld)
return NULL;
if (username == NULL) {
res = ldap_simple_bind_s(ld,NULL,NULL);
} else {
res = ldap_simple_bind_s(ld,username,password);
}
if (res!=LDAP_SUCCESS) {
ldap_unbind(ld);
return NULL;
}
return ld;
}
/* Scope argument added JM 12/23/98 */
int match_ldap_filter(LDAP *ld, char *dn, char *filter, int ldapScope)
{
LDAPMessage *msg, *entry;
int res;
res=ldap_search_s(ld,dn,ldapScope,filter,NULL,0,&msg);
if ((res!=LDAP_SUCCESS) || !msg)
return 0;
entry=ldap_first_entry(ld,msg);
if (entry==NULL)
{
ldap_msgfree(msg);
return 0;
}
ldap_msgfree(msg);
return 1;
}
static int ldap_verify_group_member(LDAP *ld, char *group, char *user, char *groupMemberAttr) {
int res;
res=ldap_compare_s(ld,group,groupMemberAttr,user);
if (res==LDAP_COMPARE_TRUE) {
return 1;
} else {
return 0;
}
}
int ldap_authenticate (request_rec *r)
{
ldap_config_struct *conf;
conn_rec *c = r->connection;
const char *sent_pw;
char *filter;
LDAPMessage *msg, *entry;
int res;
int scope;
conf = (ldap_config_struct *)
ap_get_module_config(r->per_dir_config, &ldap_module);
if(!conf->ldap_auth) return DECLINED;
/* security bug fix here (RP): if sent_pw=="", bind will succeed as anonymous ! */
if (ap_get_basic_auth_pw (r, &sent_pw) || !strlen(sent_pw)) return AUTH_REQUIRED;
/* Changed by Soren Roug */
scope = conf->searchmode;
conf->ld = ldap_open_and_bind(conf->host,
conf->port,
conf->bindname,
conf->bindpass);
/* we should have an open and bound connection. if not then error */
if (conf->ld==NULL) {
ap_log_reason("ldap bind failed",r->uri,r);
return SERVER_ERROR;
}
filter = ap_pstrcat(r->pool,
"(",
conf->userid_attr,
"=",
r->connection->user,
")",
NULL);
/* Changed this and one other occurrence from LDAP_SCOPE_whatever to
user configurable scope. JM 12/23/98 */
res=ldap_search_s(conf->ld,
conf->base,
scope,
filter,
NULL,
0,
&msg);
if ((res!=LDAP_SUCCESS) || !msg)
{
ldap_unbind(conf->ld);
ap_log_reason(ap_pstrcat(r->pool,
"can't search user ",
r->connection->user,
" in ",
conf->base,
NULL),r->uri,r);
r->connection->user=NULL;
return AUTH_REQUIRED;
}
entry=ldap_first_entry(conf->ld,msg);
if(entry) {
r->connection->user=ap_pstrdup(r->pool,ldap_get_dn(conf->ld,entry));
}
else
{
ap_log_reason(ap_pstrcat(r->pool,
"can't find ",
r->connection->user,
" in ",
conf->base,
" on server ",
conf->host,
" with filter ",
filter,
NULL),r->uri,r);
r->connection->user=NULL;
}
ldap_msgfree(msg);
/* No need to do this if r->connection->user == NULL. Bug pointed out
by Markku.Jarvinen@tpo.fi and fixed JM 3/10/99. */
if (r->connection->user != NULL)
{
if(!conf->userpassword_attr)
{
ldap_unbind(conf->ld);
conf->ld = ldap_open_and_bind(conf->host,
conf->port,
r->connection->user,
(char *)sent_pw);
if(conf->ld==NULL)
r->connection->user=NULL;
else ldap_unbind(conf->ld);
}
else
{
if(ldap_compare_s(conf->ld,
r->connection->user,
conf->userpassword_attr,
(char *)sent_pw)!=LDAP_COMPARE_TRUE)
r->connection->user=NULL;
ldap_unbind(conf->ld);
}
}
if (r->connection->user == NULL)
{
ap_log_reason(ap_pstrcat(r->pool,
"authentication failed",
NULL),r->uri,r);
return AUTH_REQUIRED;
}
else return OK;
}
int ldap_check_auth (request_rec *r) {
ldap_config_struct *conf;
array_header *reqs_arr;
require_line *reqs;
char *userdn;
int i;
int active = 0;
int scope;
char *t, *w;
/* DEBUGGING */
/*ap_log_reason("Entering ldap_check_auth",r->uri,r);*/
conf = (ldap_config_struct *)
ap_get_module_config(r->per_dir_config, &ldap_module);
reqs_arr = (array_header *)(ap_requires (r));
reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL;
/* Added by Jamie Scuglia */
if(!conf->ldap_auth) return DECLINED;
/* must have require field(s) */
if (!reqs_arr || !r->connection->user) {
return DECLINED;
}
/* Changed by Soren Roug */
scope = conf->searchmode;
/* DEBUGGING */
/* ap_log_reason(ap_pstrcat(r->pool, "reqs_arr->nelts = ", num2str(reqs_arr->nelts), NULL),r->uri,r);
*/
for(i=0; (i < reqs_arr->nelts) ; i++) {
if (! (reqs[i].method_mask & (1 << (r->method_number)))) continue;
t = reqs[i].requirement;
w = ap_getword_conf(r->pool, (const char **)(&t));
/* DEBUGGING */
/*ap_log_reason(ap_pstrcat(r->pool, "w = ", w, NULL),r->uri,r);*/
if (strcmp(w,"filter")==0)
{
active = 1;
w = ap_getword_conf (r->pool, (const char **)(&t));
conf->ld = ldap_open_and_bind(conf->host,
conf->port,
conf->bindname,
conf->bindpass);
/* we should have an open and bound connection. if not then error */
if (conf->ld==NULL) {
ap_log_reason("ldap bind failed",r->uri,r);
return SERVER_ERROR;
}
if (match_ldap_filter(conf->ld, r->connection->user, w, scope))
{
/* Added JM 12/21/98 */
if (conf->reset_username) resetUsername(r->connection->user, conf, r);
ldap_unbind(conf->ld);
return OK;
}
ldap_unbind(conf->ld);
}
else
if (strcmp(w,"valid-user")==0)
{
active = 1;
conf->ld = ldap_open_and_bind(conf->host,
conf->port,
conf->bindname,
conf->bindpass);
/* we should have an open and bound connection. */
/* if not then error */
if (conf->ld==NULL) {
ap_log_reason("ldap bind failed",r->uri,r);
return SERVER_ERROR;
}
/* Scope changed from "scope" to LDAP_SCOPE_BASE by Soren Roug. The old way makes no
sense because the search should start from the DN of r->connection->user, but if
the search fails at the top level, then we know immediately that the user doesn't
exist. Change added 7/14/99 */
if (match_ldap_filter(conf->ld,
r->connection->user,
"(objectClass=*)", LDAP_SCOPE_BASE))
{
/*ap_log_reason(ap_pstrcat(r->pool, "OK user=", r->connection->user, NULL), r->uri,r);*/
/* Added JM 12/21/98 */
if (conf->reset_username) resetUsername(r->connection->user, conf, r);
ldap_unbind(conf->ld);
return OK;
}
ldap_unbind(conf->ld);
}
/* Next two else if's added JM 12/23/98 */
else if (strcmp(w,"user")==0) {
active = 1;
w = getword_conf (r->pool, (const char **)(&t));
/*ap_log_reason(ap_pstrcat(r->pool, "comparing user ", r->connection->user, " to userdn ", w, NULL), r->uri,r);*/
/* Check if the user's full DN matches the user given in the config file. */
if (strcasecmp(r->connection->user,w)==0) {
if (conf->reset_username) resetUsername(r->connection->user, conf, r);
return OK;
}
else {
/* Check to see if the user's base username matches the user given in the config file */
userdn = ap_pstrdup(r->pool, r->connection->user);
resetUsername(r->connection->user, conf, r);
/*ap_log_reason(ap_pstrcat(r->pool, "comparing user ", r->connection->user, " to userdn ", w, NULL), r->uri,r);*/
if (strcasecmp(r->connection->user, w)==0) {
if (! conf->reset_username) {
/* NOTE: this is safe, since r->connection->user is still a large enough
piece of allocated memory to hold the full DN, as it did before. */
strcpy(r->connection->user, userdn);
}
return OK;
}
/* If the username didn't match, we still have to reset the username if the config
file told us to. Bug pointed out by Markku.Jarvinen@tpo.fi, fixed JM 3/17/99.
Note that we copy back to full DN even if conf->reset_username is not set. This
is because we may be looping through other require directives. We don't want to
permanently change r->connection->user until we're just about to return OK. */
strcpy(r->connection->user, userdn);
}
} else if (strcmp(w,"group")==0) {
w = ap_getword_conf (r->pool, (const char **)(&t));
conf->ld = ldap_open_and_bind(conf->host,
conf->port,
conf->bindname,
conf->bindpass);
/* we should have an open and bound connection. if not then error */
if (conf->ld==NULL) {
ap_log_reason("ldap bind failed",r->uri,r);
return SERVER_ERROR;
}
active = 1;
if (ldap_verify_group_member(conf->ld,w,r->connection->user,conf->groupmember_attr)) {
/*ap_log_reason(ap_pstrcat(r->pool, "found user ", r->connection->user, " in group ", w, NULL), r->uri,r);*/
if (conf->reset_username) resetUsername(r->connection->user, conf, r);
ldap_unbind(conf->ld);
return OK;
}
ldap_unbind(conf->ld);
}
}
if(!active) return DECLINED;
ap_log_reason(ap_pstrcat(r->pool,
"LDAP access denied for ",
r->connection->user,
NULL),
r->uri,r);
return AUTH_REQUIRED;
}
/* Added JM 12/21/98 */
/* This function takes username (which should be an LDAP distinguished name)
and replaces it with just the username. This may be necessary, because
otherwise the REMOTE_USER variable passed to CGI's will be the full
LDAP dn!
Note that this function is not called if the LDAPUseDNForRemoteUser config
variable is set to "on".
This now returns the attribute defined in LDAPuseridAttr, not the first half
of the DN. Bug pointed out by Dan Rich and fixed by Dan Rich and JM 1/21/00.
*/
void resetUsername(char* username, ldap_config_struct* conf, request_rec* r)
{
char** temp;
int i;
LDAP* conn;
LDAPMessage *msg, *entry;
int res;
char *filter;
int filterLen;
if (conf->ld == NULL) {
conn = ldap_open_and_bind(conf->host,
conf->port,
conf->bindname,
conf->bindpass);
if (conn == NULL) {
ap_log_reason("ldap bind failed in resetUsername", r->uri, r);
return;
}
}
else conn = conf->ld;
/* Get the entry corresponding to the user */
/* Set up a filter from the DN by copying the DN, then replacing the comma with a \0 */
filter = ap_pstrcat(r->pool, username, NULL);
filterLen = strlen(filter);
for (i = 0; filter[i] != ',' && i < filterLen; i++) ;
if (i >= filterLen) {
ap_log_reason("no comma found in resetUsername", r->uri, r);
if (conf->ld == NULL && conn != NULL) ldap_unbind(conn);
return;
}
filter[i] = '\0';
res = ldap_search_s(conn, username, LDAP_SCOPE_BASE, filter, NULL, 0, &msg);
if ((res!=LDAP_SUCCESS) || !msg) {
ap_log_reason("ldap_search_s failed in resetUsername", r->uri, r);
if (conf->ld == NULL && conn != NULL) ldap_unbind(conn);
return;
}
entry = ldap_first_entry(conn, msg);
if (! entry) {
ap_log_reason("ldap_first_entry failed in resetUsername", r->uri, r);
return;
}
/* Get the attribute defined in LDAPuseridAttr */
temp = ldap_get_values(conn, entry, conf->userid_attr);
if (! temp) {
ap_log_reason("ldap_get_values failed in resetUsername", r->uri, r);
return;
}
/* Assumes that the above ldap_get_values call only returns 1 value */
strcpy(username, temp[0]);
ldap_value_free(temp);
if (conf->ld == NULL) ldap_unbind(conn);
}
/* --------------------------------- */
module ldap_module = {
STANDARD_MODULE_STUFF,
NULL, /* initializer */
create_ldap_dir_config, /* dir config creater */
NULL, /* dir merger - default=override */
NULL, /* server config */
NULL, /* merge server config */
ldap_auth_cmds, /* command table */
NULL, /* handlers */
NULL, /* filename translation */
ldap_authenticate, /* check_user_id */
ldap_check_auth, /* check auth */
NULL, /* check access */
NULL, /* type_checker */
NULL, /* pre-run fixups */
NULL /* logger */
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment