📄 ppolicy.c
字号:
rs->sr_err = LDAP_CONSTRAINT_VIOLATION; rs->sr_text = "Password is not being changed from existing value"; pErr = PP_passwordInHistory; goto return_results; } if (pp.pwdInHistory < 1) goto do_modify; /* * Iterate through the password history, and fail on any * password matches. */ at = *pa; at.a_vals = cr; cr[1].bv_val = NULL; for(p=tl; p; p=p->next) { cr[0] = p->pw; /* FIXME: no access checking? */ rc = slap_passwd_check( op, NULL, &at, bv, &txt ); if (rc != LDAP_SUCCESS) continue; rs->sr_err = LDAP_CONSTRAINT_VIOLATION; rs->sr_text = "Password is in history of old passwords"; pErr = PP_passwordInHistory; goto return_results; } }do_modify: if (pwmod) { struct berval timestamp; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; time_t now = slap_get_time(); /* If the conn is restricted, set a callback to clear it * if the pwmod succeeds */ if (!BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn )) { slap_callback *sc = op->o_tmpcalloc( 1, sizeof( slap_callback ), op->o_tmpmemctx ); sc->sc_next = op->o_callback; /* Must use sc_response to insure we reset on success, before * the client sees the response. Must use sc_cleanup to insure * that it gets cleaned up if sc_response is not called. */ sc->sc_response = ppolicy_mod_cb; sc->sc_cleanup = ppolicy_mod_cb; op->o_callback = sc; } /* * keep the necessary pwd.. operational attributes * up to date. */ timestamp.bv_val = timebuf; timestamp.bv_len = sizeof(timebuf); slap_timestamp( &now, ×tamp ); mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 ); mods->sml_desc = ad_pwdChangedTime; if (pwmop != LDAP_MOD_DELETE) { mods->sml_op = LDAP_MOD_REPLACE; mods->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); ber_dupbv( &mods->sml_values[0], ×tamp ); BER_BVZERO( &mods->sml_values[1] ); assert( !BER_BVISNULL( &mods->sml_values[0] ) ); } else { mods->sml_op = LDAP_MOD_DELETE; } mods->sml_flags = SLAP_MOD_INTERNAL; mods->sml_next = NULL; modtail->sml_next = mods; modtail = mods; if (attr_find(e->e_attrs, ad_pwdGraceUseTime )) { mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 ); mods->sml_op = LDAP_MOD_DELETE; mods->sml_desc = ad_pwdGraceUseTime; mods->sml_flags = SLAP_MOD_INTERNAL; mods->sml_next = NULL; modtail->sml_next = mods; modtail = mods; } if (attr_find(e->e_attrs, ad_pwdAccountLockedTime )) { mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 ); mods->sml_op = LDAP_MOD_DELETE; mods->sml_desc = ad_pwdAccountLockedTime; mods->sml_flags = SLAP_MOD_INTERNAL; mods->sml_next = NULL; modtail->sml_next = mods; modtail = mods; } if (attr_find(e->e_attrs, ad_pwdFailureTime )) { mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 ); mods->sml_op = LDAP_MOD_DELETE; mods->sml_desc = ad_pwdFailureTime; mods->sml_flags = SLAP_MOD_INTERNAL; mods->sml_next = NULL; modtail->sml_next = mods; modtail = mods; } /* Delete the pwdReset attribute, since it's being reset */ if ((zapReset) && (attr_find(e->e_attrs, ad_pwdReset ))) { mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 ); mods->sml_op = LDAP_MOD_DELETE; mods->sml_desc = ad_pwdReset; mods->sml_flags = SLAP_MOD_INTERNAL; mods->sml_next = NULL; modtail->sml_next = mods; modtail = mods; } if (pp.pwdInHistory > 0) { if (hsize >= pp.pwdInHistory) { /* * We use the >= operator, since we are going to add * the existing password attribute value into the * history - thus the cardinality of history values is * about to rise by one. * * If this would push it over the limit of history * values (remembering - the password policy could have * changed since the password was last altered), we must * delete at least 1 value from the pwdHistory list. * * In fact, we delete '(#pwdHistory attrs - max pwd * history length) + 1' values, starting with the oldest. * This is easily evaluated, since the linked list is * created in ascending time order. */ mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 ); mods->sml_op = LDAP_MOD_DELETE; mods->sml_flags = SLAP_MOD_INTERNAL; mods->sml_desc = ad_pwdHistory; mods->sml_values = ch_calloc( sizeof( struct berval ), hsize - pp.pwdInHistory + 2 ); BER_BVZERO( &mods->sml_values[ hsize - pp.pwdInHistory + 1 ] ); for(i=0,p=tl; i < (hsize - pp.pwdInHistory + 1); i++, p=p->next) { BER_BVZERO( &mods->sml_values[i] ); ber_dupbv( &(mods->sml_values[i]), &p->bv ); } mods->sml_next = NULL; modtail->sml_next = mods; modtail = mods; } free_pwd_history_list( &tl ); /* * Now add the existing password into the history list. * This will be executed even if the operation is to delete * the password entirely. * * This isn't in the spec explicitly, but it seems to make * sense that the password history list is the list of all * previous passwords - even if they were deleted. Thus, if * someone tries to add a historical password at some future * point, it will fail. */ if ((pa = attr_find( e->e_attrs, pp.ad )) != NULL) { mods = (Modifications *) ch_malloc( sizeof( Modifications ) ); mods->sml_op = LDAP_MOD_ADD; mods->sml_flags = SLAP_MOD_INTERNAL; mods->sml_type.bv_val = NULL; mods->sml_desc = ad_pwdHistory; mods->sml_nvalues = NULL; mods->sml_values = ch_calloc( sizeof( struct berval ), 2 ); mods->sml_values[ 1 ].bv_val = NULL; mods->sml_values[ 1 ].bv_len = 0; make_pwd_history_value( timebuf, &mods->sml_values[0], pa ); mods->sml_next = NULL; modtail->sml_next = mods; modtail = mods; } else { Debug( LDAP_DEBUG_TRACE, "ppolicy_modify: password attr lookup failed\n", 0, 0, 0 ); } } /* * Controversial bit here. If the new password isn't hashed * (ie, is cleartext), we probably should hash it according * to the default hash. The reason for this is that we want * to use the policy if possible, but if we hash the password * before, then we're going to run into trouble when it * comes time to check the password. * * Now, the right thing to do is to use the extended password * modify operation, but not all software can do this, * therefore it makes sense to hash the new password, now * we know it passes the policy requirements. * * Of course, if the password is already hashed, then we * leave it alone. */ if ((pi->hash_passwords) && (addmod) && !newpw.bv_val && (password_scheme( &(addmod->sml_values[0]), NULL ) != LDAP_SUCCESS)) { struct berval hpw, bv; slap_passwd_hash( &(addmod->sml_values[0]), &hpw, &txt ); if (hpw.bv_val == NULL) { /* * hashing didn't work. Emit an error. */ rs->sr_err = LDAP_OTHER; rs->sr_text = txt; goto return_results; } bv = addmod->sml_values[0]; /* clear and discard the clear password */ memset(bv.bv_val, 0, bv.bv_len); ber_memfree(bv.bv_val); addmod->sml_values[0] = hpw; } } op->o_bd->bd_info = (BackendInfo *)on->on_info; be_entry_release_r( op, e ); return SLAP_CB_CONTINUE;return_results: free_pwd_history_list( &tl ); op->o_bd->bd_info = (BackendInfo *)on->on_info; be_entry_release_r( op, e ); if ( send_ctrl ) { LDAPControl *ctrl = NULL; ctrl = create_passcontrol( -1, -1, pErr ); oldctrls = add_passcontrol( op, rs, ctrl ); } send_ldap_result( op, rs ); if ( send_ctrl ) { ctrls_cleanup( op, rs, oldctrls ); } return rs->sr_err;}static intppolicy_parseCtrl( Operation *op, SlapReply *rs, LDAPControl *ctrl ){ if ( ctrl->ldctl_value.bv_len ) { rs->sr_text = "passwordPolicyRequest control value not empty"; return LDAP_PROTOCOL_ERROR; } op->o_ctrlflag[ppolicy_cid] = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; return LDAP_SUCCESS;}static intattrPretty( Syntax *syntax, struct berval *val, struct berval *out, void *ctx ){ AttributeDescription *ad = NULL; const char *err; int code; code = slap_bv2ad( val, &ad, &err ); if ( !code ) { ber_dupbv_x( out, &ad->ad_type->sat_cname, ctx ); } return code;}static intattrNormalize( slap_mask_t use, Syntax *syntax, MatchingRule *mr, struct berval *val, struct berval *out, void *ctx ){ AttributeDescription *ad = NULL; const char *err; int code; code = slap_bv2ad( val, &ad, &err ); if ( !code ) { ber_str2bv_x( ad->ad_type->sat_oid, 0, 1, out, ctx ); } return code;}static intppolicy_db_init( BackendDB *be){ slap_overinst *on = (slap_overinst *) be->bd_info; /* Has User Schema been initialized yet? */ if ( !pwd_UsSchema[0].ad[0] ) { const char *err; int i, code; for (i=0; pwd_UsSchema[i].def; i++) { code = slap_str2ad( pwd_UsSchema[i].def, pwd_UsSchema[i].ad, &err ); if ( code ) { fprintf( stderr, "User Schema Load failed %d: %s\n", code, err ); return code; } } { Syntax *syn; MatchingRule *mr; syn = ch_malloc( sizeof( Syntax )); *syn = *ad_pwdAttribute->ad_type->sat_syntax; syn->ssyn_pretty = attrPretty; ad_pwdAttribute->ad_type->sat_syntax = syn; mr = ch_malloc( sizeof( MatchingRule )); *mr = *ad_pwdAttribute->ad_type->sat_equality; mr->smr_normalize = attrNormalize; ad_pwdAttribute->ad_type->sat_equality = mr; } } on->on_bi.bi_private = ch_calloc( sizeof(pp_info), 1 ); if ( dtblsize && !pwcons ) pwcons = ch_calloc(sizeof(pw_conn), dtblsize ); return 0;}static intppolicy_db_open( BackendDB *be){ return overlay_register_control( be, LDAP_CONTROL_PASSWORDPOLICYREQUEST );}static intppolicy_close( BackendDB *be){ slap_overinst *on = (slap_overinst *) be->bd_info; pp_info *pi = on->on_bi.bi_private; free( pwcons ); free( pi->def_policy.bv_val ); free( pi ); return 0;}static char *extops[] = { LDAP_EXOP_MODIFY_PASSWD, NULL};static slap_overinst ppolicy;int ppolicy_initialize(){ LDAPAttributeType *at; const char *err; int i, code; for (i=0; pwd_OpSchema[i].def; i++) { at = ldap_str2attributetype( pwd_OpSchema[i].def, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); if ( !at ) { fprintf( stderr, "AttributeType Load failed %s %s\n", ldap_scherr2str(code), err ); return code; } code = at_add( at, 0, NULL, &err ); if ( !code ) { slap_str2ad( at->at_names[0], pwd_OpSchema[i].ad, &err ); } ldap_memfree( at ); if ( code ) { fprintf( stderr, "AttributeType Load failed %s %s\n", scherr2str(code), err ); return code; } /* Allow Manager to set these as needed */ if ( is_at_no_user_mod( (*pwd_OpSchema[i].ad)->ad_type )) { (*pwd_OpSchema[i].ad)->ad_type->sat_flags |= SLAP_AT_MANAGEABLE; } } code = register_supported_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST, SLAP_CTRL_ADD|SLAP_CTRL_BIND|SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE, extops, ppolicy_parseCtrl, &ppolicy_cid ); if ( code != LDAP_SUCCESS ) { fprintf( stderr, "Failed to register control %d\n", code ); return code; } ldap_pvt_thread_mutex_init( &chk_syntax_mutex ); ppolicy.on_bi.bi_type = "ppolicy"; ppolicy.on_bi.bi_db_init = ppolicy_db_init; ppolicy.on_bi.bi_db_open = ppolicy_db_open; ppolicy.on_bi.bi_db_close = ppolicy_close; ppolicy.on_bi.bi_op_add = ppolicy_add; ppolicy.on_bi.bi_op_bind = ppolicy_bind; ppolicy.on_bi.bi_op_compare = ppolicy_restrict; ppolicy.on_bi.bi_op_delete = ppolicy_restrict; ppolicy.on_bi.bi_op_modify = ppolicy_modify; ppolicy.on_bi.bi_op_search = ppolicy_restrict; ppolicy.on_bi.bi_connection_destroy = ppolicy_connection_destroy; ppolicy.on_bi.bi_cf_ocs = ppolicyocs; code = config_register_schema( ppolicycfg, ppolicyocs ); if ( code ) return code; return overlay_register( &ppolicy );}#if SLAPD_OVER_PPOLICY == SLAPD_MOD_DYNAMICint init_module(int argc, char *argv[]) { return ppolicy_initialize();}#endif#endif /* defined(SLAPD_OVER_PPOLICY) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -