diff options
Diffstat (limited to 'ldap/servers/slapd')
-rw-r--r-- | ldap/servers/slapd/Makefile | 2 | ||||
-rw-r--r-- | ldap/servers/slapd/main.c | 13 | ||||
-rw-r--r-- | ldap/servers/slapd/modify.c | 81 | ||||
-rw-r--r-- | ldap/servers/slapd/passwd_extop.c | 516 |
4 files changed, 567 insertions, 45 deletions
diff --git a/ldap/servers/slapd/Makefile b/ldap/servers/slapd/Makefile index 6935ac30..dc342de7 100644 --- a/ldap/servers/slapd/Makefile +++ b/ldap/servers/slapd/Makefile @@ -88,7 +88,7 @@ REGULAR_SLAPD_OBJS= abandon.o bind.o \ configdse.o pw_mgmt.o auth.o \ psearch.o conntable.o \ stubs.o protect_db.o fileio.o lite_entries.o \ - getopt_ext.o start_tls_extop.o + getopt_ext.o start_tls_extop.o passwd_extop.o FEDSE_OBJ= fedse.o FEDSE_SRC= fedse.c SLAPD_OBJS= $(REGULAR_SLAPD_OBJS) $(FEDSE_OBJ) diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c index b52df26d..346444da 100644 --- a/ldap/servers/slapd/main.c +++ b/ldap/servers/slapd/main.c @@ -1015,12 +1015,17 @@ main( int argc, char **argv) /* --ugaston: register the start-tls plugin */ #ifndef _WIN32 if ( slapd_security_library_is_initialized() != 0 ) { + + start_tls_register_plugin(); LDAPDebug( LDAP_DEBUG_PLUGIN, "Start TLS plugin registered.\n", 0, 0, 0 ); } #endif + passwd_modify_register_plugin(); + LDAPDebug( LDAP_DEBUG_PLUGIN, + "Password Modify plugin registered.\n", 0, 0, 0 ); plugin_startall(argc, argv, 1 /* Start Backends */, 1 /* Start Globals */); if (housekeeping_start((time_t)0, NULL) == NULL) { @@ -1246,12 +1251,13 @@ process_command_line(int argc, char **argv, char *myname, {"encrypt",ArgOptional,'E'}, {0,0,0}}; - char *opts_archive2db = "vd:i:a:SD:"; + char *opts_archive2db = "vd:i:a:n:SD:"; struct opt_ext long_options_archive2db[] = { {"version",ArgNone,'v'}, {"debug",ArgRequired,'d'}, {"pidfile",ArgRequired,'i'}, {"archive",ArgRequired,'a'}, + {"backEndInstName",ArgRequired,'n'}, {"allowMultipleProcesses",ArgNone,'S'}, {"instanceDir",ArgRequired,'D'}, {0,0,0}}; @@ -1486,10 +1492,11 @@ process_command_line(int argc, char **argv, char *myname, case 'w': /* set startup pid file */ start_pid_file = rel2abspath( optarg_ext ); break; - case 'n': /* which backend to do ldif2db for */ + case 'n': /* which backend to do ldif2db/bak2db for */ if (slapd_exemode == SLAPD_EXEMODE_LDIF2DB || slapd_exemode == SLAPD_EXEMODE_DBTEST || - slapd_exemode == SLAPD_EXEMODE_DB2INDEX) { + slapd_exemode == SLAPD_EXEMODE_DB2INDEX || + slapd_exemode == SLAPD_EXEMODE_ARCHIVE2DB) { /* The -n argument will give the name of a backend instance. */ cmd_line_instance_name = optarg_ext; } else if (slapd_exemode == SLAPD_EXEMODE_DB2LDIF) { diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c index 56c4de7c..86237758 100644 --- a/ldap/servers/slapd/modify.c +++ b/ldap/servers/slapd/modify.c @@ -90,17 +90,15 @@ do_modify( Slapi_PBlock *pb ) int err; int pw_change = 0; /* 0= no password change */ int ignored_some_mods = 0; + int has_password_mod = 0; /* number of password mods */ char *old_pw = NULL; /* remember the old password */ char *dn; - LDAPControl **ctrlp = NULL; LDAPDebug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 ); slapi_pblock_get( pb, SLAPI_OPERATION, &operation); ber = operation->o_ber; - slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp); - /* count the modify request */ PR_AtomicIncrement(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps); @@ -217,47 +215,45 @@ do_modify( Slapi_PBlock *pb ) /* check for password change */ if ( mod->mod_bvalues != NULL && strcasecmp( mod->mod_type, SLAPI_USERPWD_ATTR ) == 0 ){ - if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { - op_shared_log_error_access (pb, "MOD", dn, "failed to decode LDAP controls"); - send_ldap_result( pb, err, NULL, NULL, 0, NULL ); - goto free_and_return; - } - pw_change = op_shared_allow_pw_change (pb, mod, &old_pw); - if (pw_change == -1) - { - ber_bvecfree(mod->mod_bvalues); - slapi_ch_free((void **)&(mod->mod_type)); - slapi_ch_free((void **)&mod); - goto free_and_return; - } + has_password_mod++; } mod->mod_op |= LDAP_MOD_BVALUES; slapi_mods_add_ldapmod (&smods, mod); } - if ( tag == LBER_ERROR && !ctrlp ) + /* check for decoding error */ + if ( tag == LBER_ERROR ) { op_shared_log_error_access (pb, "MOD", dn, "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL ); goto free_and_return; } - if ( slapi_mods_get_num_mods (&smods) == 0 ) + /* decode the optional controls - put them in the pblock */ + if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { - int lderr; - char *emsg; + op_shared_log_error_access (pb, "MOD", dn, "failed to decode LDAP controls"); + send_ldap_result( pb, err, NULL, NULL, 0, NULL ); + goto free_and_return; + } - if ( ignored_some_mods ) { - lderr = LDAP_UNWILLING_TO_PERFORM; - emsg = "no modifiable attributes specified"; - } else { - lderr = LDAP_PROTOCOL_ERROR; - emsg = "no modifications specified"; + /* if there are any password mods, see if they are allowed */ + if (has_password_mod) { + /* iterate through the mods looking for password mods */ + for (mod = slapi_mods_get_first_mod(&smods); + mod; + mod = slapi_mods_get_next_mod(&smods)) { + if ( mod->mod_bvalues != NULL && + strcasecmp( mod->mod_type, SLAPI_USERPWD_ATTR ) == 0 ) { + /* assumes controls have already been decoded and placed + in the pblock */ + pw_change = op_shared_allow_pw_change (pb, mod, &old_pw); + if (pw_change == -1) { + goto free_and_return; + } + } } - op_shared_log_error_access (pb, "MOD", dn, emsg); - send_ldap_result( pb, lderr, NULL, emsg, 0, NULL ); - goto free_and_return; } if (!pb->pb_conn->c_isreplication_session && @@ -269,19 +265,23 @@ do_modify( Slapi_PBlock *pb ) goto free_and_return; } - /* - * in LDAPv3 there can be optional control extensions on - * the end of an LDAPMessage. we need to read them in and - * pass them to the backend. - */ - if ( !ctrlp ) { - if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) + /* see if there were actually any mods to perform */ + if ( slapi_mods_get_num_mods (&smods) == 0 ) { - op_shared_log_error_access (pb, "MOD", dn, "failed to decode LDAP controls"); - send_ldap_result( pb, err, NULL, NULL, 0, NULL ); + int lderr; + char *emsg; + + if ( ignored_some_mods ) { + lderr = LDAP_UNWILLING_TO_PERFORM; + emsg = "no modifiable attributes specified"; + } else { + lderr = LDAP_PROTOCOL_ERROR; + emsg = "no modifications specified"; + } + op_shared_log_error_access (pb, "MOD", dn, emsg); + send_ldap_result( pb, lderr, NULL, emsg, 0, NULL ); goto free_and_return; } - } #ifdef LDAP_DEBUG LDAPDebug( LDAP_DEBUG_ARGS, "modifications:\n", 0, 0, 0 ); @@ -441,8 +441,7 @@ static int modify_internal_pb (Slapi_PBlock *pb) pw_change = op_shared_allow_pw_change (pb, *mod, &old_pw); if (pw_change == -1) { - opresult = LDAP_PARAM_ERROR; - slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult); + /* The internal result code will already have been set by op_shared_allow_pw_change() */ return 0; } } diff --git a/ldap/servers/slapd/passwd_extop.c b/ldap/servers/slapd/passwd_extop.c new file mode 100644 index 00000000..c4412746 --- /dev/null +++ b/ldap/servers/slapd/passwd_extop.c @@ -0,0 +1,516 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2004 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* + * Password Modify - LDAP Extended Operation. + * RFC 3062 + * + * + * This plugin implements the "Password Modify - LDAP3" + * extended operation for LDAP. The plugin function is called by + * the server if an LDAP client request contains the OID: + * "1.3.6.1.4.1.4203.1.11.1". + * + */ + +#include <stdio.h> +#include <string.h> +#include <private/pprio.h> + + +#include <prio.h> +#include <ssl.h> +#include "slap.h" +#include "slapi-plugin.h" +#include "fe.h" + +/* Type of connection for this operation;*/ +#define LDAP_EXTOP_PASSMOD_CONN_SECURE + +/* Uncomment the following line FOR TESTING: allows non-SSL connections to use the password change extended op */ +/* #undef LDAP_EXTOP_PASSMOD_CONN_SECURE */ + +/* ber tags for the PasswdModifyRequestValue sequence */ +#define LDAP_EXTOP_PASSMOD_TAG_USERID 0x80U +#define LDAP_EXTOP_PASSMOD_TAG_OLDPWD 0x81U +#define LDAP_EXTOP_PASSMOD_TAG_NEWPWD 0x82U + +/* OID of the extended operation handled by this plug-in */ +#define EXOP_PASSWD_OID "1.3.6.1.4.1.4203.1.11.1" + + +Slapi_PluginDesc passwdopdesc = { "passwd_modify_plugin", "Netscape", "0.1", + "Password Modify extended operation plugin" }; + +/* Check SLAPI_USERPWD_ATTR attribute of the directory entry + * return 0, if the userpassword attribute contains the given pwd value + * return -1, if userPassword attribute is absent for given Entry + * return LDAP_INVALID_CREDENTIALS,if userPassword attribute and given pwd don't match + */ +static int passwd_check_pwd(Slapi_Entry *targetEntry, const char *pwd){ + int rc = LDAP_SUCCESS; + Slapi_Attr *attr = NULL; + Slapi_Value cv; + Slapi_Value **bvals; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> passwd_check_pwd\n", 0, 0, 0 ); + + slapi_value_init_string(&cv,pwd); + + if ( (rc = slapi_entry_attr_find( targetEntry, SLAPI_USERPWD_ATTR, &attr )) == 0 ) + { /* we have found the userPassword attribute and it has some value */ + bvals = attr_get_present_values( attr ); + if ( slapi_pw_find_sv( bvals, &cv ) != 0 ) + { + rc = LDAP_INVALID_CREDENTIALS; + } + } + + value_done(&cv); + LDAPDebug( LDAP_DEBUG_TRACE, "<= passwd_check_pwd: %d\n", rc, 0, 0 ); + + /* if the userPassword attribute is absent then rc is -1 */ + return rc; +} + + +/* Searches the dn in directory, + * If found : fills in slapi_entry structure and returns 0 + * If NOT found : returns the search result as LDAP_NO_SUCH_OBJECT + */ +static int +passwd_modify_getEntry( const char *dn, Slapi_Entry **e2 ) { + int search_result = 0; + Slapi_DN sdn; + LDAPDebug( LDAP_DEBUG_TRACE, "=> passwd_modify_getEntry\n", 0, 0, 0 ); + slapi_sdn_init_dn_byref( &sdn, dn ); + if ((search_result = slapi_search_internal_get_entry( &sdn, NULL, e2, + plugin_get_default_component_id())) != LDAP_SUCCESS ){ + LDAPDebug (LDAP_DEBUG_TRACE, "passwd_modify_getEntry: No such entry-(%s), err (%d)\n", + dn, search_result, 0); + } + + slapi_sdn_done( &sdn ); + LDAPDebug( LDAP_DEBUG_TRACE, "<= passwd_modify_getEntry: %d\n", search_result, 0, 0 ); + return search_result; +} + + +/* Construct Mods pblock and perform the modify operation + * Sets result of operation in SLAPI_PLUGIN_INTOP_RESULT + */ +static int passwd_apply_mods(const char *dn, Slapi_Mods *mods) +{ + Slapi_PBlock pb; + Slapi_Operation *operation= NULL; + int ret=0; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> passwd_apply_mods\n", 0, 0, 0 ); + + if (mods && (slapi_mods_get_num_mods(mods) > 0)) + { + pblock_init(&pb); + slapi_modify_internal_set_pb (&pb, dn, + slapi_mods_get_ldapmods_byref(mods), + NULL, /* Controls */ + NULL, /* UniqueID */ + pw_get_componentID(), /* PluginID */ + 0); /* Flags */ + + /* Plugin operations are INTERNAL by default, bypass it to enforce ACL checks */ + slapi_pblock_get (&pb, SLAPI_OPERATION, &operation); + + ret =slapi_modify_internal_pb (&pb); + + slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &ret); + + if (ret != LDAP_SUCCESS){ + LDAPDebug(LDAP_DEBUG_TRACE, "WARNING: passwordPolicy modify error %d on entry '%s'\n", + ret, dn, 0); + } + + pblock_done(&pb); + } + + LDAPDebug( LDAP_DEBUG_TRACE, "<= passwd_apply_mods: %d\n", ret, 0, 0 ); + + return ret; +} + + + +/* Modify the userPassword attribute field of the entry */ +static int passwd_modify_userpassword(Slapi_Entry *targetEntry, const char *newPasswd) +{ + char *dn = NULL; + int ret = 0; + Slapi_Mods smods; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> passwd_modify_userpassword\n", 0, 0, 0 ); + + slapi_mods_init (&smods, 0); + dn = slapi_entry_get_ndn( targetEntry ); + slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, SLAPI_USERPWD_ATTR, newPasswd); + + + ret = passwd_apply_mods(dn, &smods); + + slapi_mods_done(&smods); + + LDAPDebug( LDAP_DEBUG_TRACE, "<= passwd_modify_userpassword: %d\n", ret, 0, 0 ); + + return ret; +} + +/* Password Modify Extended operation plugin function */ +int +passwd_modify_extop( Slapi_PBlock *pb ) +{ + char *oid = NULL; + char *bindDN = NULL; + char *dn = NULL; + char *oldPasswd = NULL; + char *newPasswd = NULL; + char *errMesg = NULL; + char **reqvals = NULL; + int ret=0, rc=0; + unsigned long tag=0, len=-1; + LDAPControl **ctrlp = NULL; /* unused */ + Slapi_Operation *operation = NULL; /* unused */ + struct berval *extop_value = NULL; + BerElement *ber = NULL; + Slapi_Entry *targetEntry=NULL; + Connection *conn = NULL; + /* Slapi_DN sdn; */ + + LDAPDebug( LDAP_DEBUG_TRACE, "=> passwd_modify_extop\n", 0, 0, 0 ); + /* Get the pb ready for sending Password Modify Extended Responses back to the client. + * The only requirement is to set the LDAP OID of the extended response to the EXOP_PASSWD_OID. */ + + if ( slapi_pblock_set( pb, SLAPI_EXT_OP_RET_OID, EXOP_PASSWD_OID ) != 0 ) { + errMesg = "Could not set extended response oid.\n"; + rc = LDAP_OPERATIONS_ERROR; + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_extop", + errMesg ); + goto free_and_return; + } + + /* Before going any further, we'll make sure that the right extended operation plugin + * has been called: i.e., the OID shipped whithin the extended operation request must + * match this very plugin's OID: EXOP_PASSWD_OID. */ + if ( slapi_pblock_get( pb, SLAPI_EXT_OP_REQ_OID, &oid ) != 0 ) { + errMesg = "Could not get OID value from request.\n"; + rc = LDAP_OPERATIONS_ERROR; + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_extop", + errMesg ); + goto free_and_return; + } else { + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_extop", + "Received extended operation request with OID %s\n", oid ); + } + + if ( strcasecmp( oid, EXOP_PASSWD_OID ) != 0) { + errMesg = "Request OID does not match Passwd OID.\n"; + rc = LDAP_OPERATIONS_ERROR; + goto free_and_return; + } else { + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_extop", + "Password Modify extended operation request confirmed.\n" ); + } + + /* Now , at least we know that the request was indeed a Password Modify one. */ + +#ifdef LDAP_EXTOP_PASSMOD_CONN_SECURE + /* Allow password modify only for SSL/TLS established connections */ + conn = pb->pb_conn; + if ( (conn->c_flags & CONN_FLAG_SSL) != CONN_FLAG_SSL) { + errMesg = "Operation requires a secure connection.\n"; + rc = LDAP_CONFIDENTIALITY_REQUIRED; + goto free_and_return; + } +#endif + + /* Get the ber value of the extended operation */ + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); + + if ((ber = ber_init(extop_value)) == NULL) + { + errMesg = "PasswdModify Request decode failed.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto free_and_return; + } + + /* Format of request to parse + * + * PasswdModifyRequestValue ::= SEQUENCE { + * userIdentity [0] OCTET STRING OPTIONAL + * oldPasswd [1] OCTET STRING OPTIONAL + * newPasswd [2] OCTET STRING OPTIONAL } + */ + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); + + /* ber parse code */ + if ( ber_scanf( ber, "{") == LBER_ERROR ) + { + LDAPDebug( LDAP_DEBUG_ANY, + "ber_scanf failed :{\n", 0, 0, 0 ); + errMesg = "ber_scanf failed\n"; + rc = LDAP_PROTOCOL_ERROR; + goto free_and_return; + } else { + tag = ber_peek_tag( ber, &len); + } + + + /* identify userID field by tags */ + if (tag == LDAP_EXTOP_PASSMOD_TAG_USERID ) + { + if ( ber_scanf( ber, "a", &dn) == LBER_ERROR ) + { + LDAPDebug( LDAP_DEBUG_ANY, + "ber_scanf failed :{\n", 0, 0, 0 ); + errMesg = "ber_scanf failed at userID parse.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto free_and_return; + } + + tag = ber_peek_tag( ber, &len); + } + + + /* identify oldPasswd field by tags */ + if (tag == LDAP_EXTOP_PASSMOD_TAG_OLDPWD ) + { + if ( ber_scanf( ber, "a", &oldPasswd ) == LBER_ERROR ) + { + LDAPDebug( LDAP_DEBUG_ANY, + "ber_scanf failed :{\n", 0, 0, 0 ); + errMesg = "ber_scanf failed at oldPasswd parse.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto free_and_return; + } + tag = ber_peek_tag( ber, &len); + } else { + errMesg = "Current passwd must be supplied by the user.\n"; + rc = LDAP_PARAM_ERROR; + goto free_and_return; + } + + /* identify newPasswd field by tags */ + if (tag == LDAP_EXTOP_PASSMOD_TAG_NEWPWD ) + { + if ( ber_scanf( ber, "a", &newPasswd ) == LBER_ERROR ) + { + LDAPDebug( LDAP_DEBUG_ANY, + "ber_scanf failed :{\n", 0, 0, 0 ); + errMesg = "ber_scanf failed at newPasswd parse.\n"; + rc = LDAP_PROTOCOL_ERROR; + goto free_and_return; + } + } else { + errMesg = "New passwd must be supplied by the user.\n"; + rc = LDAP_PARAM_ERROR; + goto free_and_return; + } + + /* Uncomment for debugging, otherwise we don't want to leak the password values into the log... */ + /* LDAPDebug( LDAP_DEBUG_ARGS, "passwd: dn (%s), oldPasswd (%s) ,newPasswd (%s)\n", + dn, oldPasswd, newPasswd); */ + + + if (oldPasswd == NULL || *oldPasswd == '\0') { + /* Refuse to handle this operation because current password is not provided */ + errMesg = "Current passwd must be supplied by the user.\n"; + rc = LDAP_PARAM_ERROR; + goto free_and_return; + } + + /* We don't implement password generation, so if the request implies + * that they asked us to do that, we must refuse to process it */ + if (newPasswd == NULL || *newPasswd == '\0') { + /* Refuse to handle this operation because we don't allow password generation */ + errMesg = "New passwd must be supplied by the user.\n"; + rc = LDAP_PARAM_ERROR; + goto free_and_return; + } + + /* Get Bind DN */ + slapi_pblock_get( pb, SLAPI_CONN_DN, &bindDN ); + + /* If the connection is bound anonymously, we must refuse to process this operation. */ + if (bindDN == NULL || *bindDN == '\0') { + /* Refuse the operation because they're bound anonymously */ + errMesg = "Anonymous Binds are not allowed.\n"; + rc = LDAP_INSUFFICIENT_ACCESS; + goto free_and_return; + } + + /* Determine the target DN for this operation */ + /* Did they give us a DN ? */ + if (dn == NULL || *dn == '\0') { + /* Get the DN from the bind identity on this connection */ + dn = bindDN; + LDAPDebug( LDAP_DEBUG_ANY, + "Missing userIdentity in request, using the bind DN instead.\n", + 0, 0, 0 ); + } + + slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, dn ); + + /* Now we have the DN, look for the entry */ + ret = passwd_modify_getEntry(dn, &targetEntry); + /* If we can't find the entry, then that's an error */ + if (ret) { + /* Couldn't find the entry, fail */ + errMesg = "No such Entry exists.\n" ; + rc = LDAP_NO_SUCH_OBJECT ; + goto free_and_return; + } + + /* First thing to do is to ask access control if the bound identity has + rights to modify the userpassword attribute on this entry. If not, then + we fail immediately with insufficient access. This means that we don't + leak any useful information to the client such as current password + wrong, etc. + */ + + operation_set_target_spec (pb->pb_op, slapi_entry_get_sdn(targetEntry)); + slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot ); + + /* In order to perform the access control check , we need to select a backend (even though + * we don't actually need it otherwise). + */ + { + Slapi_Backend *be = NULL; + + be = slapi_mapping_tree_find_backend_for_sdn(slapi_entry_get_sdn(targetEntry)); + if (NULL == be) { + errMesg = "Failed to find backend for target entry"; + rc = LDAP_OPERATIONS_ERROR; + goto free_and_return; + } + slapi_pblock_set(pb, SLAPI_BACKEND, be); + } + + ret = slapi_access_allowed ( pb, targetEntry, SLAPI_USERPWD_ATTR, NULL, SLAPI_ACL_WRITE ); + if ( ret != LDAP_SUCCESS ) { + errMesg = "Insufficient access rights\n"; + rc = LDAP_INSUFFICIENT_ACCESS; + goto free_and_return; + } + + /* Now we have the entry which we want to modify + * They gave us a password (old), check it against the target entry + * Is the old password valid ? + */ + ret = passwd_check_pwd(targetEntry, oldPasswd); + if (ret) { + /* No, then we fail this operation */ + errMesg = "Invalid oldPasswd value.\n"; + rc = ret; + goto free_and_return; + } + + + /* Now we're ready to make actual password change */ + ret = passwd_modify_userpassword(targetEntry, newPasswd); + if (ret != LDAP_SUCCESS) { + /* Failed to modify the password, e.g. because insufficient access allowed */ + errMesg = "Failed to update password\n"; + rc = ret; + goto free_and_return; + } + + LDAPDebug( LDAP_DEBUG_TRACE, "<= passwd_modify_extop: %d\n", rc, 0, 0 ); + + /* Free anything that we allocated above */ + free_and_return: + + if ( targetEntry != NULL ){ + slapi_entry_free (targetEntry); + } + + if ( ber != NULL ){ + ber_free(ber, 1); + ber = NULL; + } + + + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_extop", + errMesg ); + send_ldap_result( pb, rc, NULL, errMesg, 0, NULL ); + + + return( SLAPI_PLUGIN_EXTENDED_SENT_RESULT ); + +}/* passwd_modify_extop */ + + +static char *passwd_oid_list[] = { + EXOP_PASSWD_OID, + NULL +}; + + +static char *passwd_name_list[] = { + "passwd_modify_extop", + NULL +}; + + +/* Initialization function */ +int passwd_modify_init( Slapi_PBlock *pb ) +{ + char **argv; + char *oid; + + /* Get the arguments appended to the plugin extendedop directive. The first argument + * (after the standard arguments for the directive) should contain the OID of the + * extended operation. + */ + + if ( slapi_pblock_get( pb, SLAPI_PLUGIN_ARGV, &argv ) != 0 ) { + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_init", "Could not get argv\n" ); + return( -1 ); + } + + /* Compare the OID specified in the configuration file against the Passwd OID. */ + + if ( argv == NULL || strcmp( argv[0], EXOP_PASSWD_OID ) != 0 ) { + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_init", + "OID is missing or is not %s\n", EXOP_PASSWD_OID ); + return( -1 ); + } else { + oid = slapi_ch_strdup( argv[0] ); + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_init", + "Registering plug-in for Password Modify extended op %s.\n", oid ); + } + + /* Register the plug-in function as an extended operation + * plug-in function that handles the operation identified by + * OID 1.3.6.1.4.1.4203.1.11.1 . Also specify the version of the server + * plug-in */ + if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&passwdopdesc ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *) passwd_modify_extop ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, passwd_oid_list ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, passwd_name_list ) != 0 ) { + + slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_init", + "Failed to set plug-in version, function, and OID.\n" ); + return( -1 ); + } + + return( 0 ); +} + +int passwd_modify_register_plugin() +{ + slapi_register_plugin( "extendedop", 1 /* Enabled */, "passwd_modify_init", + passwd_modify_init, "Password Modify extended operation", + passwd_oid_list, NULL ); + + return 0; +} + |