mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-02-03 20:40:05 -05:00
Merge branch 'master' into 'master'
Draft: New contribution module "unicodepw" See merge request openldap/openldap!232
This commit is contained in:
commit
27e6d313f1
4 changed files with 700 additions and 0 deletions
57
contrib/slapd-modules/unicodepw/Makefile
Normal file
57
contrib/slapd-modules/unicodepw/Makefile
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# $OpenLDAP$
|
||||
# This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
#
|
||||
# Copyright 2021 The OpenLDAP Foundation.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted only as authorized by the OpenLDAP
|
||||
# Public License.
|
||||
#
|
||||
# A copy of this license is available in the file LICENSE in the
|
||||
# top-level directory of the distribution or, alternatively, at
|
||||
# <http://www.OpenLDAP.org/license.html>.
|
||||
|
||||
LDAP_SRC = ../../..
|
||||
LDAP_BUILD = $(LDAP_SRC)
|
||||
LDAP_INC = -I$(LDAP_BUILD)/include -I$(LDAP_SRC)/include -I$(LDAP_SRC)/servers/slapd
|
||||
LDAP_LIB = $(LDAP_BUILD)/libraries/libldap_r/libldap_r.la \
|
||||
$(LDAP_BUILD)/libraries/liblber/liblber.la
|
||||
|
||||
LIBTOOL = $(LDAP_BUILD)/libtool
|
||||
CC = gcc
|
||||
OPT = -g -O2 -Wall -Wextra
|
||||
DEFS = -DSLAPD_OVER_UNICODEPW=SLAPD_MOD_DYNAMIC
|
||||
INCS = $(LDAP_INC)
|
||||
LIBS = $(LDAP_LIB)
|
||||
|
||||
PROGRAMS = unicodepw.la
|
||||
LTVER = 0:0:0
|
||||
|
||||
prefix=/usr/local
|
||||
exec_prefix=$(prefix)
|
||||
ldap_subdir=/openldap
|
||||
|
||||
libdir=$(exec_prefix)/lib
|
||||
libexecdir=$(exec_prefix)/libexec
|
||||
moduledir = $(libexecdir)$(ldap_subdir)
|
||||
|
||||
.SUFFIXES: .c .o .lo
|
||||
|
||||
.c.lo:
|
||||
$(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(INCS) -c $<
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
unicodepw.la: unicodepw.lo
|
||||
$(LIBTOOL) --mode=link $(CC) $(OPT) -version-info $(LTVER) \
|
||||
-rpath $(moduledir) -module -o $@ $? $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.lo *.la .libs
|
||||
|
||||
install: $(PROGRAMS)
|
||||
mkdir -p $(DESTDIR)$(moduledir)
|
||||
for p in $(PROGRAMS) ; do \
|
||||
$(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(moduledir) ; \
|
||||
done
|
||||
|
||||
34
contrib/slapd-modules/unicodepw/README
Normal file
34
contrib/slapd-modules/unicodepw/README
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
This directory contains a slapd overlay, "unicodepw".
|
||||
|
||||
The overlay unicodepw restricts all LDAP modification requests, so that
|
||||
only password changes for MS unicodePwd are possible. All other LDAP
|
||||
requests will not be observed.
|
||||
|
||||
Usage:
|
||||
man slapo-unicodepw (see slapo-unicodepw.5)
|
||||
|
||||
Build:
|
||||
Use the Makefile to compile this plugin.
|
||||
|
||||
---
|
||||
|
||||
This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
|
||||
Copyright 2021 The OpenLDAP Foundation. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted only as authorized by the OpenLDAP
|
||||
Public License.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted only as authorized by the OpenLDAP
|
||||
Public License.
|
||||
|
||||
A copy of this license is available in the file LICENSE in the
|
||||
top-level directory of the distribution or, alternatively, at
|
||||
<http://www.OpenLDAP.org/license.html>.
|
||||
|
||||
The attached patch file is derived from OpenLDAP Software.
|
||||
All of the modifications to OpenLDAP Software represented in
|
||||
the following patch(es) were developed by Ingo Voss ingo.voss@gmail.com.
|
||||
I have not assigned rights and/or interest in this work to any party.
|
||||
292
contrib/slapd-modules/unicodepw/slapo-unicodepw.5
Normal file
292
contrib/slapd-modules/unicodepw/slapo-unicodepw.5
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
.TH UNICODEPW 5 "RELEASEDATE" "OpenLDAP LDVERSION"
|
||||
.\" Copyright 2021 The OpenLDAP Foundation, All Rights Reserved.
|
||||
.\" Copying restrictions apply. See the COPYRIGHT file.
|
||||
.\" $OpenLDAP$
|
||||
.SH NAME
|
||||
unicodepw \- Overlay for openlap
|
||||
.SH SYNOPSIS
|
||||
The overlay
|
||||
.B unicodepw
|
||||
restricts all LDAP modification requests, so that only
|
||||
password changes for MS unicodePwd are possible.
|
||||
All other LDAP requests will not be observed.
|
||||
.SH DESCRIPTION
|
||||
Some remote access technologies for company networks (e.g. VPN gateways)
|
||||
require a MS Active Directory Service (ADS) in the backend to log in with the
|
||||
personal ADS account. In some cases (e.g. home office workers/max. password age),
|
||||
it must be possible to allow password changes from remote.
|
||||
But this requires "write access" (modify) from the gateway to the ADS.
|
||||
|
||||
A direct access from the gateway to the ADS is a bad idea, so using
|
||||
OpenLDAP as proxy
|
||||
.B (slapd-ldap)
|
||||
in the DMZ can mitigate the security risks.
|
||||
All LDAP search results, initiated by the gateway can be restricted by ACLs.
|
||||
That will happen in the response from ADS. LDAP requests that only modify
|
||||
(write, modify, ..) cannot be protecte with ACLs, because slapd-ldap does not
|
||||
support restricting incoming request.
|
||||
|
||||
The backend slapd-ldap itself cannot be set to read-only, because changing the password requires "write" access.
|
||||
The overlay
|
||||
.B denyop
|
||||
can only restrict LDAP requests, but it does not look
|
||||
inside the request. Using overlay denyop would only restrict the access by
|
||||
allowing ALL modifications to ADS, so that other manipulation are possible too.
|
||||
That was the reason to write the extra overlay
|
||||
.B unicodepw.
|
||||
|
||||
The
|
||||
.B unicodepw
|
||||
overlay to
|
||||
.BR slapd (8)
|
||||
services is checking the modification requests, if the modification request
|
||||
is a password change for MS ADS. All other modifications are denied.
|
||||
.LP
|
||||
The conditions for changing the password in MS ADS are described in
|
||||
https://msdn.microsoft.com/en-us/library/cc223248 and KB269190.
|
||||
Microsoft stores the password in the attribute unicodePwd. It is not readable,
|
||||
but writeable. The sequence requires ONE LDAP modification with TWO operations to
|
||||
change the password:
|
||||
|
||||
.RS
|
||||
.nf
|
||||
dn: <userdn>
|
||||
changetype: modify
|
||||
delete: UnicodePwd
|
||||
UnicodePwd::<old password>
|
||||
-
|
||||
add: UnicodePwd
|
||||
UnicodePwd::<new password>
|
||||
.fi
|
||||
.RE
|
||||
|
||||
The old password is required, no matter what rights the changing context
|
||||
(bind dn) in the ADS has.
|
||||
|
||||
The
|
||||
.B unicodepw
|
||||
checks
|
||||
.RS
|
||||
.nf
|
||||
- The number of the operations: only TWO are allowed
|
||||
- The type of operations: only DELETE and ADD are allowed
|
||||
- The order of the operations: first DELETE, second ADD
|
||||
- The attribute which is modified (configurable)
|
||||
- The parent dn of the user who is changed (configurable)
|
||||
.fi
|
||||
.RE
|
||||
If one of these checks fails, the overlay will deny the request BEFORE sending
|
||||
the request to the ADS!
|
||||
.SH CONFIGURATION
|
||||
.LP
|
||||
The
|
||||
.B unicodepw
|
||||
is configured in the ETCDIR/slapd.conf.
|
||||
At the moment NO dynamic config support is available for the overlay unicodepw.
|
||||
.TP
|
||||
.B moduleload unicodepw
|
||||
Load the module in the slapd context. Don't forget to set the
|
||||
.B modulepath
|
||||
option.
|
||||
.TP
|
||||
.B overlay unicodepw
|
||||
This directive adds the unicodepw overlay to the current backend.
|
||||
.TP
|
||||
.B unicodepw pwattr <password attribute>
|
||||
This directive configures the attribute which is checked in the modification. Usually "unicodePwd" should be
|
||||
used here.
|
||||
.TP
|
||||
.B unicodepw userbase <DN, where the users in the ADS are located>
|
||||
This directive configures the distinguished name of the user base.
|
||||
With the userbase directive you can restrict password changes to a dedicated location in the
|
||||
ADS. This location then should contain only users who use remote access.
|
||||
For all other users in the ADS a password change is NOT possible from the VPN gateway (outside).
|
||||
.TP
|
||||
.B unicodepw subtree <yes|no>
|
||||
If this directive is set to yes, password changes are allowed for all users under "userbase" and
|
||||
all DNs below (subtree)
|
||||
.TP
|
||||
.B unicodepw logactivity <yes|no>
|
||||
Enable the additional logging for all operations, checks and results from the unicodepw module.
|
||||
The global parameter "log level" MUST be set to stats)!
|
||||
This Parameter was intoduced to prevent the noise from the module during normal operation
|
||||
of slapd (the default log level is already stats).
|
||||
Since the module implements a security function, the admin likes to know and log, who is changing the password
|
||||
and with witch result. Then set logactivity to "yes"!
|
||||
|
||||
.SH CONFIGURATION HINTS
|
||||
|
||||
Since the unicodepw only restricts the modify request, the module
|
||||
.B denyop
|
||||
must used too, to restrict all other unwanted LDAP requests.
|
||||
|
||||
Additionally, to configure slapd-ldap to proxy unicodePwd changes, at least the
|
||||
unicodePwd must be defined in a private schema (see EXAMPLES).
|
||||
|
||||
All other LDAP operations comming from the access gateway should restict with ACLs!
|
||||
|
||||
For your own security, the connection between LDAP client (e.g. VPN gateway)
|
||||
and OpenLDAP should be protected by SSL/TLS.
|
||||
|
||||
The connection between OpenLDAP and Microsoft ADS MUST be encrypted via SSL/TLS.
|
||||
Microsoft does not allow password changes on a unencrypted session!
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
Only the important parts for the slapd configuration:
|
||||
|
||||
.RS
|
||||
.nf
|
||||
#################################
|
||||
# including private schema
|
||||
#################################
|
||||
include /etc/openldap/schema/myADschema.schema
|
||||
|
||||
#################################
|
||||
# overlay configuration
|
||||
#################################
|
||||
modulepath /usr/lib/openldap/modules
|
||||
moduleload back_ldap
|
||||
moduleload denyop
|
||||
moduleload unicodepw
|
||||
|
||||
overlay denyop
|
||||
# possible denyops add,bind,compare,delete,
|
||||
# extended,modify,modrdn,search,unbind
|
||||
denyop add,compare,delete,modrdn
|
||||
|
||||
overlay unicodepw
|
||||
unicodepw pwattr "UnicodePwd"
|
||||
unicodepw userbase "ou=remoteUsers,dc=company,dc=com"
|
||||
unicodepw logactivity "yes"
|
||||
|
||||
#################################
|
||||
# proxy configuration
|
||||
#################################
|
||||
database ldap
|
||||
rebind-as-user yes
|
||||
suffix "dc=company,dc=com"
|
||||
uri "ldap://ads1.company.com/ ldap://ads2.company.com"
|
||||
chase-referrals no
|
||||
protocol-version 3
|
||||
.fi
|
||||
.RE
|
||||
|
||||
Please don't forget to configure the ACLs in the proxy backend and the TLS configuration for slapd!
|
||||
Parameters like:
|
||||
.B TLSCACertificateFile, TLSCertificateFile, TLSCertificateKeyFile, TLSVerifyClient, TLSCipherSuite
|
||||
should configured globally and
|
||||
.B security, tls, access
|
||||
in the database section!
|
||||
|
||||
For testing purposes, it can be useful to create the encoded MS unicode password.
|
||||
The following commands should do it:
|
||||
.TP
|
||||
.nf
|
||||
.B echo <password> | perl -ne 'chomp;print pack \*(lqv*\*(rq, unpack \*(lqC*\*(rq,\*(lq\e\*(rq$_\e\*(rq\*(rq' | base64
|
||||
.fi
|
||||
The output can be included in the modify request in the attribute unicodePwd.
|
||||
Example:
|
||||
.TP
|
||||
.nf
|
||||
.B echo password123_ | perl -ne 'chomp;print pack \*(lqv*\*(rq, unpack \*(lqC*\*(rq,\*(lq\e\*(rq$_\e\*(rq\*(rq' | base64
|
||||
the resulting attribute is:
|
||||
unicodePwd::IgBwAGEAcwBzAHcAbwByAGQAMQAyADMAXwAiAA==
|
||||
.fi
|
||||
.RE
|
||||
|
||||
|
||||
In the section CONFIGURATION HINTS, we talked about a private schema. Here is an example for it:
|
||||
.RS
|
||||
.nf
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.750 NAME 'groupType'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.114.7.4.2.0.33 NAME 'memberOf'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.656 NAME 'userPrincipalName'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.52 NAME 'lastLogon'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.159 NAME 'accountExpires'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.96 NAME 'pwdLastSet'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.221 NAME 'sAMAccountName'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.8 NAME 'userAccountControl'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.4.90 NAME 'unicodePwd'
|
||||
SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' )
|
||||
|
||||
objectclass ( 1.2.840.113556.1.5.9 NAME 'user'
|
||||
DESC 'a user'
|
||||
SUP inetOrgPerson STRUCTURAL
|
||||
MUST ( cn )
|
||||
MAY ( userPassword $ memberOf $ userPrincipalName $
|
||||
distinguishedName $ lastLogon $ accountExpires $
|
||||
pwdLastSet $ sAMAccountName $ userAccountControl $
|
||||
unicodePwd ) )
|
||||
|
||||
objectclass ( 1.2.840.113556.1.5.8 NAME 'group'
|
||||
DESC 'a group of users'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( groupType $ cn )
|
||||
MAY ( member ) )
|
||||
.fi
|
||||
.RE
|
||||
|
||||
.SH LOGGING/DEBUG
|
||||
If "stats" is enabled, each password change request and all checks are logged and if they fail, the reasons are logged too!
|
||||
For informations about the values during modification, please refer to the log before unicodepw. Grep for the same
|
||||
connection id and operation number (conn= and op=)!
|
||||
|
||||
.B Example for a logging output, every thing is ok:
|
||||
.nf
|
||||
conn=1005 op=2 unicodepw: INFO => configured UsersBase nDN => <ou=remoteUsers,dc=company,dc=com>
|
||||
conn=1005 op=2 unicodepw: INFO => configured pwattr => <UnicodePwd>
|
||||
conn=1005 op=2 unicodepw: INFO => configured logactivity => <1>
|
||||
conn=1005 op=2 unicodepw: INFO => Parent DN from user, who is changed => <ou=remoteUsers,dc=company,dc=com>
|
||||
conn=1005 op=2 unicodepw: INFO => User, who is changed <cn=remoteuser1,ou=remoteUsers,dc=company,dc=com>
|
||||
conn=1005 op=2 unicodepw: OK => Attribute in Modification (DEL) is the configured pwattr!
|
||||
conn=1005 op=2 unicodepw: OK => Attribute in Modification (ADD) is the configured pwattr!
|
||||
conn=1005 op=2 unicodepw: ACCEPT => UnicodePwd changing is permitted!
|
||||
.fi
|
||||
|
||||
|
||||
.B Example for a logging output, user DN is wrong:
|
||||
.nf
|
||||
conn=1006 op=2 unicodepw: INFO => configured UsersBase nDN => <ou=remoteUsers,dc=company,dc=com>
|
||||
conn=1006 op=2 unicodepw: INFO => configured pwattr => <UnicodePwd>
|
||||
conn=1006 op=2 unicodepw: INFO => configured logactivity => <1>
|
||||
conn=1006 op=2 unicodepw: INFO => Parent DN from user, who is changed => <ou=Users,dc=company,dc=com>
|
||||
conn=1006 op=2 unicodepw: INFO => User, who is changed <cn=normaluser,ou=Users,dc=company,dc=com>
|
||||
conn=1006 op=2 unicodepw: DENY => UserBase from <cn=normaluser,ou=Users,dc=company,dc=com> is not in configured UserBase!
|
||||
conn=1006 op=2 unicodepw: OK => Attribute in Modification (DEL) is the configured pwattr!
|
||||
conn=1006 op=2 unicodepw: OK => Attribute in Modification (ADD) is the configured pwattr!
|
||||
.fi
|
||||
|
||||
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
ETCDIR/slapd.conf
|
||||
default slapd configuration file
|
||||
.SH SEE ALSO
|
||||
.BR slapd.conf (5),
|
||||
.BR slapd\-config (5),
|
||||
.BR slapd\-ldap (5),
|
||||
.BR slapd (8),
|
||||
overlay
|
||||
.BR denyop
|
||||
and https://msdn.microsoft.com/en-us/library/cc223248 and KB269190 for description of password change.
|
||||
.SH AUTHOR
|
||||
This module is written in 2016-2020 by Ingo Voss (ingo.voss@gmail.com)
|
||||
317
contrib/slapd-modules/unicodepw/unicodepw.c
Normal file
317
contrib/slapd-modules/unicodepw/unicodepw.c
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
/* unicodepw.c - acceppt only password change for MS Active Directory */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2021 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
/* ACKNOLEDGEDMENTS:
|
||||
* This work was initially developed by Ingo Voss (ingo.voss@gmail.com)
|
||||
* for inclusion in OpenLDAP Software.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#ifdef SLAPD_OVER_UNICODEPW
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "lber.h"
|
||||
|
||||
|
||||
typedef struct unicodepw_conf {
|
||||
struct berval attr;
|
||||
struct berval userbase;
|
||||
int log_activity;
|
||||
int subtree_search;
|
||||
} unicodepw_conf;
|
||||
|
||||
|
||||
static int
|
||||
unicodepw_mod( Operation *op, SlapReply *rs ) {
|
||||
|
||||
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
|
||||
unicodepw_conf *u_conf = (unicodepw_conf *) on->on_bi.bi_private;
|
||||
int deny = 0;
|
||||
int i = 1;
|
||||
Modifications *m;
|
||||
|
||||
/* from Config for container, where users are located */
|
||||
struct berval user_base_ndn;
|
||||
dnNormalize( 0, NULL, NULL, &u_conf->userbase, &user_base_ndn, op->o_tmpmemctx );
|
||||
|
||||
/* get parent DN from user, who is changed */
|
||||
struct berval user_parent_ndn;
|
||||
dnParent( &op->o_req_ndn, &user_parent_ndn );
|
||||
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
/* logging config */
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: INFO => configured UsersBase nDN => <%s>\n",
|
||||
op->o_connid, op->o_opid, user_base_ndn.bv_val );
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: INFO => configured pwattr => <%s>\n",
|
||||
op->o_connid, op->o_opid, u_conf->attr.bv_val );
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: INFO => configured logactivity => <%d>\n",
|
||||
op->o_connid, op->o_opid, u_conf->log_activity );
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: INFO => configured subtree => <%d>\n",
|
||||
op->o_connid, op->o_opid, u_conf->subtree_search );
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: INFO => User, who is changed <%s>\n",
|
||||
op->o_connid, op->o_opid, op->o_req_ndn.bv_val );
|
||||
/* logging User and parent DN */
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: INFO => Parent DN from user, who is changed => <%s>\n",
|
||||
op->o_connid, op->o_opid, user_parent_ndn.bv_val );
|
||||
}
|
||||
|
||||
/* check if user is in configured UserBase */
|
||||
if ( u_conf->subtree_search == 1 ) {
|
||||
int found = 0;
|
||||
while (!BER_BVISEMPTY( &user_parent_ndn )) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DEBUG => <%s>\n",
|
||||
op->o_connid, op->o_opid, user_parent_ndn.bv_val );
|
||||
}
|
||||
if ( strcmp( user_parent_ndn.bv_val, user_base_ndn.bv_val ) == 0 ) {
|
||||
found = 1;
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: INFO: Found User under => <%s>\n",
|
||||
op->o_connid, op->o_opid, user_parent_ndn.bv_val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
dnParent( &user_parent_ndn , &user_parent_ndn );
|
||||
}
|
||||
if ( found == 0 ) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DENY => UserBase from <%s> is not in configured UserBase\n",
|
||||
op->o_connid, op->o_opid, op->o_req_dn.bv_val );
|
||||
}
|
||||
deny = 1;
|
||||
}
|
||||
} else {
|
||||
if ( strcmp( user_parent_ndn.bv_val, user_base_ndn.bv_val ) != 0 ) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DENY => UserBase from <%s> is not in configured UserBase\n",
|
||||
op->o_connid, op->o_opid, op->o_req_dn.bv_val );
|
||||
}
|
||||
deny = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* load Modifications and process */
|
||||
if ( !(m = op->orm_modlist) ) {
|
||||
op->o_bd->bd_info = (BackendInfo *) on->on_info;
|
||||
send_ldap_error( op, rs, LDAP_INVALID_SYNTAX, "unique_modify() got null op.orm_modlist" );
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/* successful load */
|
||||
for ( ; m; m = m->sml_next ) {
|
||||
/* only attribute UnicodePwd allowed! */
|
||||
if ( strcasecmp( m->sml_type.bv_val, u_conf->attr.bv_val ) != 0 ) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DENY => Attribute in Modification (%s) is not the configured pwattr!\n",
|
||||
op->o_connid, op->o_opid,
|
||||
m->sml_op == LDAP_MOD_ADD ? "ADD" : (m->sml_op == LDAP_MOD_DELETE ? "DEL" : "other") );
|
||||
}
|
||||
deny = 1;
|
||||
} else {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: OK => Attribute in Modification (%s) is the configured pwattr!\n",
|
||||
op->o_connid, op->o_opid,
|
||||
m->sml_op == LDAP_MOD_ADD ? "ADD" : (m->sml_op == LDAP_MOD_DELETE ? "DEL" : "other") );
|
||||
}
|
||||
}
|
||||
|
||||
/* only DEL and ADD allowed */
|
||||
if ( m->sml_op == LDAP_MOD_DELETE || m->sml_op == LDAP_MOD_ADD ) {
|
||||
if ( m->sml_op == LDAP_MOD_DELETE && i != 1 ) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DENY => Modification DEL not in first place!%s\n",
|
||||
op->o_connid, op->o_opid, "" );
|
||||
}
|
||||
deny = 1;
|
||||
} else if ( m->sml_op == LDAP_MOD_ADD && i != 2 ) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DENY => Modification ADD not in second place!%s\n",
|
||||
op->o_connid, op->o_opid, "" );
|
||||
}
|
||||
deny = 1;
|
||||
}
|
||||
} else {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DENY => Modification not in ADD or DEL!%s\n",
|
||||
op->o_connid, op->o_opid, "" );
|
||||
}
|
||||
deny = 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if ( i != 3 ) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: DENY => More or less than TWO modifications!%s\n",
|
||||
op->o_connid, op->o_opid, "" );
|
||||
}
|
||||
deny = 1;
|
||||
}
|
||||
|
||||
if ( !deny ) {
|
||||
if ( u_conf->log_activity == 1 ) {
|
||||
Debug( LDAP_DEBUG_STATS,
|
||||
"conn=%lu op=%lu unicodepw: ACCEPT => UnicodePwd changing is permitted!%s\n",
|
||||
op->o_connid, op->o_opid, "" );
|
||||
}
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
op->o_bd->bd_info = (BackendInfo *)on->on_info;
|
||||
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "operation not allowed by unicodepw!" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
unicodepw_config(
|
||||
BackendDB *be,
|
||||
const char *fname,
|
||||
int lineno,
|
||||
int argc,
|
||||
char **argv )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *) be->bd_info;
|
||||
unicodepw_conf *u_conf = (unicodepw_conf *) on->on_bi.bi_private;
|
||||
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"\tlline: %d,\t argv[1]: %s,\t argv[2]: %s\n",
|
||||
lineno, argv[1], argv[2] );
|
||||
|
||||
if ( strcasecmp( argv[0], "unicodepw" ) == 0 ) {
|
||||
if ( argc != 3 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: " "wrong configuration line, use: " "\"unicodepw <param> <value>\" line.%s\n",
|
||||
fname, lineno, "" );
|
||||
return 1;
|
||||
}
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"unicodepw: config => param: %s, value: %s%s\n",
|
||||
argv[1] ,argv[2], "" );
|
||||
if ( strcasecmp(argv[1], "pwattr" ) == 0 ) {
|
||||
if ( u_conf->attr.bv_val ) {
|
||||
/* if already defined! */
|
||||
ch_free( u_conf->attr.bv_val );
|
||||
}
|
||||
ber_str2bv( argv[ 2 ], 0, 1, &u_conf->attr );
|
||||
} else if ( strcasecmp(argv[1], "userbase" ) == 0 ) {
|
||||
if ( u_conf->userbase.bv_val ) {
|
||||
/* if already defined! */
|
||||
ch_free( u_conf->userbase.bv_val );
|
||||
}
|
||||
ber_str2bv( argv[ 2 ], 0, 1, &u_conf->userbase );
|
||||
} else if ( strcasecmp(argv[1], "logactivity" ) == 0 ) {
|
||||
if ( strcasecmp( argv[ 2 ], "yes" ) == 0 ) {
|
||||
u_conf->log_activity = 1;
|
||||
} else if ( strcasecmp( argv[ 2 ], "no" ) == 0 ) {
|
||||
u_conf->log_activity = 0;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: " "wrong configuration line, use: " "\"unicodepw logactivity <yes|no>\" line.%s\n",
|
||||
fname, lineno, "" );
|
||||
return SLAP_CONF_UNKNOWN;
|
||||
}
|
||||
} else if ( strcasecmp(argv[1], "subtree" ) == 0 ) {
|
||||
if ( strcasecmp( argv[ 2 ], "yes" ) == 0 ) {
|
||||
u_conf->subtree_search = 1;
|
||||
} else if ( strcasecmp( argv[ 2 ], "no" ) == 0 ) {
|
||||
u_conf->subtree_search = 0;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: " "wrong configuration line, use: " "\"unicodepw subtree <yes|no>\" line.%s\n",
|
||||
fname, lineno, "" );
|
||||
return SLAP_CONF_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
return SLAP_CONF_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
return SLAP_CONF_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unicodepw_over_init( BackendDB *be )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *) be->bd_info;
|
||||
unicodepw_conf *u_conf;
|
||||
|
||||
u_conf = (unicodepw_conf *)ch_malloc( sizeof(unicodepw_conf) );
|
||||
memset( u_conf, 0, sizeof(unicodepw_conf) );
|
||||
on->on_bi.bi_private = u_conf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unicodepw_destroy( BackendDB *be )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *) be->bd_info;
|
||||
unicodepw_conf *u_conf = (unicodepw_conf *) on->on_bi.bi_private;
|
||||
|
||||
if ( u_conf ) {
|
||||
ch_free ( u_conf );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static slap_overinst unicodepw;
|
||||
|
||||
int
|
||||
unicodepw_initialize( void ) {
|
||||
memset( &unicodepw, 0, sizeof( slap_overinst ) );
|
||||
|
||||
unicodepw.on_bi.bi_type = "unicodepw";
|
||||
unicodepw.on_bi.bi_db_init = unicodepw_over_init;
|
||||
unicodepw.on_bi.bi_db_config = unicodepw_config;
|
||||
unicodepw.on_bi.bi_db_destroy = unicodepw_destroy;
|
||||
|
||||
unicodepw.on_bi.bi_op_modify = unicodepw_mod;
|
||||
unicodepw.on_response = NULL /* unicodepw_response */;
|
||||
|
||||
return overlay_register( &unicodepw );
|
||||
}
|
||||
|
||||
#if SLAPD_OVER_UNICODEPW == SLAPD_MOD_DYNAMIC
|
||||
int
|
||||
init_module( int argc, char *argv[] ) {
|
||||
return unicodepw_initialize();
|
||||
}
|
||||
#endif /* SLAPD_OVER_UNICODEPW == SLAPD_MOD_DYNAMIC */
|
||||
|
||||
#endif /* defined(SLAPD_OVER_UNICODEPW) */
|
||||
Loading…
Reference in a new issue