⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppolicy.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			 * get provided. By default, this is what we do			 *			 * But if the hash_passwords flag is set, we hash			 * any cleartext password attribute values via the			 * default password hashing scheme.			 */		if ((pi->hash_passwords) &&			(password_scheme( &(pa->a_vals[0]), NULL ) != LDAP_SUCCESS)) {			struct berval hpw;			slap_passwd_hash( &(pa->a_vals[0]), &hpw, &txt );			if (hpw.bv_val == NULL) {				/*				 * hashing didn't work. Emit an error.				 */				rs->sr_err = LDAP_OTHER;				rs->sr_text = txt;				send_ldap_error( op, rs, LDAP_OTHER, "Password hashing failed" );				return rs->sr_err;			}			memset( pa->a_vals[0].bv_val, 0, pa->a_vals[0].bv_len);			ber_memfree( pa->a_vals[0].bv_val );			pa->a_vals[0].bv_val = hpw.bv_val;			pa->a_vals[0].bv_len = hpw.bv_len;		}		/* If password aging is in effect, set the pwdChangedTime */		if ( pp.pwdMaxAge || pp.pwdMinAge ) {			struct berval timestamp;			char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];			time_t now = slap_get_time();			timestamp.bv_val = timebuf;			timestamp.bv_len = sizeof(timebuf);			slap_timestamp( &now, &timestamp );			attr_merge_one( op->ora_e, ad_pwdChangedTime, &timestamp, &timestamp );		}	}	return SLAP_CB_CONTINUE;}static intppolicy_mod_cb( Operation *op, SlapReply *rs ){	slap_callback *sc = op->o_callback;	op->o_callback = sc->sc_next;	if ( rs->sr_err == LDAP_SUCCESS ) {		ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );		BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );	}	op->o_tmpfree( sc, op->o_tmpmemctx );	return SLAP_CB_CONTINUE;}static intppolicy_modify( Operation *op, SlapReply *rs ){	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;	pp_info			*pi = on->on_bi.bi_private;	int			i, rc, mod_pw_only, pwmod, pwmop = -1, deladd,				hsize = 0;	PassPolicy		pp;	Modifications		*mods = NULL, *modtail = NULL,				*ml, *delmod, *addmod;	Attribute		*pa, *ha, at;	const char		*txt;	pw_hist			*tl = NULL, *p;	int			zapReset, send_ctrl = 0;	Entry			*e;	struct berval		newpw = BER_BVNULL, oldpw = BER_BVNULL,				*bv, cr[2];	LDAPPasswordPolicyError pErr = PP_noError;	LDAPControl 		**oldctrls = NULL;	op->o_bd->bd_info = (BackendInfo *)on->on_info;	rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );	op->o_bd->bd_info = (BackendInfo *)on;	if ( rc != LDAP_SUCCESS ) return SLAP_CB_CONTINUE;	/* If this is a replica, we may need to tweak some of the	 * master's modifications. Otherwise, just pass it through.	 */	if ( be_shadow_update( op )) {		Modifications **prev;		int got_del_grace = 0, got_del_lock = 0, got_pw = 0, got_del_fail = 0;		Attribute *a_grace, *a_lock, *a_fail;		a_grace = attr_find( e->e_attrs, ad_pwdGraceUseTime );		a_lock = attr_find( e->e_attrs, ad_pwdAccountLockedTime );		a_fail = attr_find( e->e_attrs, ad_pwdFailureTime );		for( prev = &op->orm_modlist, ml = *prev; ml; ml = *prev ) {			if ( ml->sml_desc == slap_schema.si_ad_userPassword )				got_pw = 1;			/* If we're deleting an attr that didn't exist,			 * drop this delete op			 */			if ( ml->sml_op == LDAP_MOD_DELETE ) {				int drop = 0;				if ( ml->sml_desc == ad_pwdGraceUseTime ) {					got_del_grace = 1;					if ( !a_grace )						drop = 1;				} else				if ( ml->sml_desc == ad_pwdAccountLockedTime ) {					got_del_lock = 1;					if ( !a_lock )						drop = 1;				} else				if ( ml->sml_desc == ad_pwdFailureTime ) {					got_del_fail = 1;					if ( !a_fail )						drop = 1;				}				if ( drop ) {					*prev = ml->sml_next;					ml->sml_next = NULL;					slap_mods_free( ml, 1 );					continue;				}			}			prev = &ml->sml_next;		}		/* If we're resetting the password, make sure grace, accountlock,		 * and failure also get removed.		 */		if ( got_pw ) {			if ( a_grace && !got_del_grace ) {				ml = (Modifications *) ch_malloc( sizeof( Modifications ) );				ml->sml_op = LDAP_MOD_DELETE;				ml->sml_flags = SLAP_MOD_INTERNAL;				ml->sml_type.bv_val = NULL;				ml->sml_desc = ad_pwdGraceUseTime;				ml->sml_values = NULL;				ml->sml_nvalues = NULL;				ml->sml_next = NULL;				*prev = ml;				prev = &ml->sml_next;			}			if ( a_lock && !got_del_lock ) {				ml = (Modifications *) ch_malloc( sizeof( Modifications ) );				ml->sml_op = LDAP_MOD_DELETE;				ml->sml_flags = SLAP_MOD_INTERNAL;				ml->sml_type.bv_val = NULL;				ml->sml_desc = ad_pwdAccountLockedTime;				ml->sml_values = NULL;				ml->sml_nvalues = NULL;				ml->sml_next = NULL;				*prev = ml;			}			if ( a_fail && !got_del_fail ) {				ml = (Modifications *) ch_malloc( sizeof( Modifications ) );				ml->sml_op = LDAP_MOD_DELETE;				ml->sml_flags = SLAP_MOD_INTERNAL;				ml->sml_type.bv_val = NULL;				ml->sml_desc = ad_pwdFailureTime;				ml->sml_values = NULL;				ml->sml_nvalues = NULL;				ml->sml_next = NULL;				*prev = ml;			}		}		op->o_bd->bd_info = (BackendInfo *)on->on_info;		be_entry_release_r( op, e );		return SLAP_CB_CONTINUE;	}	/* Did we receive a password policy request control? */	if ( op->o_ctrlflag[ppolicy_cid] ) {		send_ctrl = 1;	}	/* See if this is a pwdModify exop. If so, we can	 * access the plaintext passwords from that request.	 */	{		slap_callback *sc;		for ( sc = op->o_callback; sc; sc=sc->sc_next ) {			if ( sc->sc_response == slap_replog_cb &&				sc->sc_private ) {				req_pwdexop_s *qpw = sc->sc_private;				newpw = qpw->rs_new;				oldpw = qpw->rs_old;			   	break;			}		}	}	ppolicy_get( op, e, &pp );	for ( ml = op->orm_modlist,			pwmod = 0, mod_pw_only = 1,			deladd = 0, delmod = NULL,			addmod = NULL,			zapReset = 1;		ml != NULL; modtail = ml, ml = ml->sml_next )	{		if ( ml->sml_desc == pp.ad ) {			pwmod = 1;			pwmop = ml->sml_op;			if ((deladd == 0) && (ml->sml_op == LDAP_MOD_DELETE) &&				(ml->sml_values) && !BER_BVISNULL( &ml->sml_values[0] ))			{				deladd = 1;				delmod = ml;			}			if ((deladd == 1) && ((ml->sml_op == LDAP_MOD_ADD) ||				  (ml->sml_op == LDAP_MOD_REPLACE)))			{				deladd = 2;			}			if ((ml->sml_op == LDAP_MOD_ADD) ||				(ml->sml_op == LDAP_MOD_REPLACE))			{				addmod = ml;				/* FIXME: there's no easy way to ensure				 * that add does not cause multiple				 * userPassword values; one way (that 				 * would be consistent with the single				 * password constraint) would be to turn				 * add into replace); another would be				 * to disallow add.				 *				 * Let's check at least that a single value				 * is being added				 */				assert( addmod->sml_values != NULL );				assert( !BER_BVISNULL( &addmod->sml_values[ 0 ] ) );				if ( !BER_BVISNULL( &addmod->sml_values[ 1 ] ) ) {					rs->sr_err = LDAP_CONSTRAINT_VIOLATION; 					rs->sr_text = "Password policy only allows one password value";					goto return_results;				}			}		} else if ( !is_at_operational( ml->sml_desc->ad_type ) ) {			mod_pw_only = 0;			/* modifying something other than password */		}		/*		 * If there is a request to explicitly add a pwdReset		 * attribute, then we suppress the normal behaviour on		 * password change, which is to remove the pwdReset		 * attribute.		 *		 * This enables an administrator to assign a new password		 * and place a "must reset" flag on the entry, which will		 * stay until the user explicitly changes his/her password.		 */		if (ml->sml_desc == ad_pwdReset ) {			if ((ml->sml_op == LDAP_MOD_ADD) ||				(ml->sml_op == LDAP_MOD_REPLACE))				zapReset = 0;		}	}		if (!BER_BVISEMPTY( &pwcons[op->o_conn->c_conn_idx].dn ) && !mod_pw_only ) {		if ( dn_match( &op->o_conn->c_ndn,				&pwcons[op->o_conn->c_conn_idx].dn )) {			Debug( LDAP_DEBUG_TRACE,				"connection restricted to password changing only\n", 0, 0, 0 );			rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 			rs->sr_text = "Operations are restricted to bind/unbind/abandon/StartTLS/modify password";			pErr = PP_changeAfterReset;			goto return_results;		} else {			ch_free( pwcons[op->o_conn->c_conn_idx].dn.bv_val );			BER_BVZERO( &pwcons[op->o_conn->c_conn_idx].dn );		}	}	/*	 * if we have a "safe password modify policy", then we need to check if we're doing	 * a delete (with the old password), followed by an add (with the new password).	 *	 * If we don't have this, then we fail with an error. We also skip all the checks if	 * the root user is bound. Root can do anything, including avoid the policies.	 */	if (!pwmod) goto do_modify;	/*	 * Did we get a valid add mod?	 */	if (!addmod) {		rs->sr_err = LDAP_OTHER;		rs->sr_text = "Internal Error";		Debug( LDAP_DEBUG_TRACE,			"cannot locate modification supplying new password\n", 0, 0, 0 );		goto return_results;	}	/*	 * Build the password history list in ascending time order	 * We need this, even if the user is root, in order to maintain	 * the pwdHistory operational attributes properly.	 */	if (pp.pwdInHistory > 0 && (ha = attr_find( e->e_attrs, ad_pwdHistory ))) {		struct berval oldpw;		time_t oldtime;		for(i=0; ha->a_nvals[i].bv_val; i++) {			rc = parse_pwdhistory( &(ha->a_nvals[i]), NULL,				&oldtime, &oldpw );			if (rc != LDAP_SUCCESS) continue; /* invalid history entry */			if (oldpw.bv_val) {				add_to_pwd_history( &tl, oldtime, &oldpw,					&(ha->a_nvals[i]) );				oldpw.bv_val = NULL;				oldpw.bv_len = 0;			}		}		for(p=tl; p; p=p->next, hsize++); /* count history size */	}	if (be_isroot( op )) goto do_modify;	/* This is a pwdModify exop that provided the old pw.	 * We need to create a Delete mod for this old pw and 	 * let the matching value get found later	 */	if (pp.pwdSafeModify && oldpw.bv_val ) {		ml = (Modifications *)ch_calloc( sizeof( Modifications ), 1 );		ml->sml_op = LDAP_MOD_DELETE;		ml->sml_flags = SLAP_MOD_INTERNAL;		ml->sml_desc = pp.ad;		ml->sml_type = pp.ad->ad_cname;		ml->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );		ber_dupbv( &ml->sml_values[0], &oldpw );		BER_BVZERO( &ml->sml_values[1] );		ml->sml_next = op->orm_modlist;		op->orm_modlist = ml;		delmod = ml;		deladd = 2;	}	if (pp.pwdSafeModify && deladd != 2) {		Debug( LDAP_DEBUG_TRACE,			"change password must use DELETE followed by ADD/REPLACE\n",			0, 0, 0 );		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;		rs->sr_text = "Must supply old password to be changed as well as new one";		pErr = PP_mustSupplyOldPassword;		goto return_results;	}	if (!pp.pwdAllowUserChange) {		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;		rs->sr_text = "User alteration of password is not allowed";		pErr = PP_passwordModNotAllowed;		goto return_results;	}	if (pp.pwdMinAge > 0) {		time_t pwtime = (time_t)-1, now;		int age;		if ((pa = attr_find( e->e_attrs, ad_pwdChangedTime )) != NULL)			pwtime = parse_time( pa->a_nvals[0].bv_val );		now = slap_get_time();		age = (int)(now - pwtime);		if ((pwtime != (time_t)-1) && (age < pp.pwdMinAge)) {			rs->sr_err = LDAP_CONSTRAINT_VIOLATION;			rs->sr_text = "Password is too young to change";			pErr = PP_passwordTooYoung;			goto return_results;		}	}	/* pa is used in password history check below, be sure it's set */	if ((pa = attr_find( e->e_attrs, pp.ad )) != NULL && delmod) {		/*		 * we have a password to check		 */		const char *txt;				bv = oldpw.bv_val ? &oldpw : delmod->sml_values;		/* FIXME: no access checking? */		rc = slap_passwd_check( op, NULL, pa, bv, &txt );		if (rc != LDAP_SUCCESS) {			Debug( LDAP_DEBUG_TRACE,				"old password check failed: %s\n", txt, 0, 0 );						rs->sr_err = LDAP_UNWILLING_TO_PERFORM;			rs->sr_text = "Must supply correct old password to change to new one";			pErr = PP_mustSupplyOldPassword;			goto return_results;		} else {			int i;						/*			 * replace the delete value with the (possibly hashed)			 * value which is currently in the password.			 */			for ( i = 0; !BER_BVISNULL( &delmod->sml_values[i] ); i++ ) {				free( delmod->sml_values[i].bv_val );				BER_BVZERO( &delmod->sml_values[i] );			}			free( delmod->sml_values );			delmod->sml_values = ch_calloc( sizeof(struct berval), 2 );			BER_BVZERO( &delmod->sml_values[1] );			ber_dupbv( &(delmod->sml_values[0]),  &(pa->a_nvals[0]) );		}	}	bv = newpw.bv_val ? &newpw : &addmod->sml_values[0];	if (pp.pwdCheckQuality > 0) {		rc = check_password_quality( bv, &pp, &pErr, e );		if (rc != LDAP_SUCCESS) {			rs->sr_err = rc;			rs->sr_text = "Password fails quality checking policy";			goto return_results;		}	}	if (pa) {		/*		 * Last check - the password history.		 */		/* FIXME: no access checking? */		if (slap_passwd_check( op, NULL, pa, bv, &txt ) == LDAP_SUCCESS) {			/*			 * This is bad - it means that the user is attempting			 * to set the password to the same as the old one.			 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -