diff --git a/contrib/slapd-modules/unicodepw/Makefile b/contrib/slapd-modules/unicodepw/Makefile new file mode 100644 index 0000000000..baf1c9fa44 --- /dev/null +++ b/contrib/slapd-modules/unicodepw/Makefile @@ -0,0 +1,57 @@ +# $OpenLDAP$ +# This work is part of OpenLDAP Software . +# +# 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 +# . + +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 + diff --git a/contrib/slapd-modules/unicodepw/README b/contrib/slapd-modules/unicodepw/README new file mode 100644 index 0000000000..aa048d8e46 --- /dev/null +++ b/contrib/slapd-modules/unicodepw/README @@ -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 . + +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 +. + +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. diff --git a/contrib/slapd-modules/unicodepw/slapo-unicodepw.5 b/contrib/slapd-modules/unicodepw/slapo-unicodepw.5 new file mode 100644 index 0000000000..d1d5bc7494 --- /dev/null +++ b/contrib/slapd-modules/unicodepw/slapo-unicodepw.5 @@ -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: +changetype: modify +delete: UnicodePwd +UnicodePwd:: +- +add: UnicodePwd +UnicodePwd:: +.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 +This directive configures the attribute which is checked in the modification. Usually "unicodePwd" should be +used here. +.TP +.B unicodepw userbase +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 +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 +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 | 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 => +conn=1005 op=2 unicodepw: INFO => configured pwattr => +conn=1005 op=2 unicodepw: INFO => configured logactivity => <1> +conn=1005 op=2 unicodepw: INFO => Parent DN from user, who is changed => +conn=1005 op=2 unicodepw: INFO => User, who is changed +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 => +conn=1006 op=2 unicodepw: INFO => configured pwattr => +conn=1006 op=2 unicodepw: INFO => configured logactivity => <1> +conn=1006 op=2 unicodepw: INFO => Parent DN from user, who is changed => +conn=1006 op=2 unicodepw: INFO => User, who is changed +conn=1006 op=2 unicodepw: DENY => UserBase from 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) diff --git a/contrib/slapd-modules/unicodepw/unicodepw.c b/contrib/slapd-modules/unicodepw/unicodepw.c new file mode 100644 index 0000000000..ee22b727ff --- /dev/null +++ b/contrib/slapd-modules/unicodepw/unicodepw.c @@ -0,0 +1,317 @@ +/* unicodepw.c - acceppt only password change for MS Active Directory */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * 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 + * . + */ + /* 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 + +#include +#include + +#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 \" 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 \" 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 \" 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) */