Exemplo n.º 1
0
/* updates counter - installed on add/delete only if required */
static int
dds_counter_cb( Operation *op, SlapReply *rs )
{
	assert( rs->sr_type == REP_RESULT );

	if ( rs->sr_err == LDAP_SUCCESS ) {
		dds_info_t	*di = op->o_callback->sc_private;

		ldap_pvt_thread_mutex_lock( &di->di_mutex );
		switch ( op->o_tag ) {
		case LDAP_REQ_DELETE:
			assert( di->di_num_dynamicObjects > 0 );
			di->di_num_dynamicObjects--;
			break;

		case LDAP_REQ_ADD:
			assert( di->di_num_dynamicObjects < di->di_max_dynamicObjects );
			di->di_num_dynamicObjects++;
			break;

		default:
			LDAP_BUG();
		}
		ldap_pvt_thread_mutex_unlock( &di->di_mutex );
	}

	return dds_freeit_cb( op, rs );
}
Exemplo n.º 2
0
static int
dds_expire_cb( Operation *op, SlapReply *rs )
{
	dds_cb_t	*dc = (dds_cb_t *)op->o_callback->sc_private;
	dds_expire_t	*de;
	int		rc;

	switch ( rs->sr_type ) {
	case REP_SEARCH:
		/* alloc list and buffer for berval all in one */
		de = op->o_tmpalloc( sizeof( dds_expire_t ) + rs->sr_entry->e_nname.bv_len + 1,
			op->o_tmpmemctx );

		de->de_next = dc->dc_ndnlist;
		dc->dc_ndnlist = de;

		de->de_ndn.bv_len = rs->sr_entry->e_nname.bv_len;
		de->de_ndn.bv_val = (char *)&de[ 1 ];
		memcpy( de->de_ndn.bv_val, rs->sr_entry->e_nname.bv_val,
			rs->sr_entry->e_nname.bv_len + 1 );
		rc = 0;
		break;

	case REP_SEARCHREF:
	case REP_RESULT:
		rc = rs->sr_err;
		break;

	default:
		LDAP_BUG();
	}

	return rc;
}
Exemplo n.º 3
0
void quorum_global_init() {
	int rc;

	assert(quorum_list == QR_POISON);
	rc = ldap_pvt_thread_mutex_init(&quorum_mutex);
	if (rc) {
		Debug( LDAP_DEBUG_ANY, "mutex_init failed for quorum_mutex, rc = %d\n", rc );
		LDAP_BUG();
		exit( EXIT_FAILURE );
	}
	quorum_list = NULL;
}
Exemplo n.º 4
0
/* callback that counts the returned entries, since the search
 * does not get to the point in slap_send_search_entries where
 * the actual count occurs */
static int
dds_count_cb( Operation *op, SlapReply *rs )
{
	int	*nump = (int *)op->o_callback->sc_private;

	switch ( rs->sr_type ) {
	case REP_SEARCH:
		(*nump)++;
		break;

	case REP_SEARCHREF:
	case REP_RESULT:
		break;

	default:
		LDAP_BUG();
	}

	return 0;
}
Exemplo n.º 5
0
int
meta_back_cancel(
	metaconn_t		*mc,
	Operation		*op,
	SlapReply		*rs,
	ber_int_t		msgid,
	int			candidate,
	ldap_back_send_t	sendok )
{
	metainfo_t		*mi = (metainfo_t *)op->o_bd->be_private;

	metatarget_t		*mt = mi->mi_targets[ candidate ];
	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];

	int			rc = LDAP_OTHER;

	Debug( LDAP_DEBUG_TRACE, ">>> %s meta_back_cancel[%d] msgid=%d\n",
		op->o_log_prefix, candidate, msgid );

	/* default behavior */
	if ( META_BACK_TGT_ABANDON( mt ) ) {
		rc = ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );

	} else if ( META_BACK_TGT_IGNORE( mt ) ) {
		rc = ldap_pvt_discard( msc->msc_ld, msgid );

	} else if ( META_BACK_TGT_CANCEL( mt ) ) {
		rc = ldap_cancel_s( msc->msc_ld, msgid, NULL, NULL );

	} else {
		LDAP_BUG();
	}

	Debug( LDAP_DEBUG_TRACE, "<<< %s meta_back_cancel[%d] err=%d\n",
		op->o_log_prefix, candidate, rc );

	return rc;
}
Exemplo n.º 6
0
static int
aci_mask(
	Operation		*op,
	Entry			*e,
	AttributeDescription	*desc,
	struct berval		*val,
	struct berval		*aci,
	int			nmatch,
	regmatch_t		*matches,
	slap_access_t		*grant,
	slap_access_t		*deny,
	slap_aci_scope_t	asserted_scope )
{
	struct berval		bv,
				scope,
				perms,
				type,
				opts,
				sdn;
	int			rc;

	ACL_INIT( *grant );
	ACL_INIT( *deny );

	assert( !BER_BVISNULL( &desc->ad_cname ) );

	/* parse an aci of the form:
		oid # scope # action;rights;attr;rights;attr
			$ action;rights;attr;rights;attr # type # subject

	   [NOTE: the following comment is very outdated,
	   as the draft version it refers to (Ando, 2004-11-20)].

	   See draft-ietf-ldapext-aci-model-04.txt section 9.1 for
	   a full description of the format for this attribute.
	   Differences: "this" in the draft is "self" here, and
	   "self" and "public" is in the position of type.

	   <scope> = {entry|children|subtree}
	   <type> = {public|users|access-id|subtree|onelevel|children|
	             self|dnattr|group|role|set|set-ref}

	   This routine now supports scope={ENTRY,CHILDREN}
	   with the semantics:
	     - ENTRY applies to "entry" and "subtree";
	     - CHILDREN applies to "children" and "subtree"
	 */

	/* check that the aci has all 5 components */
	if ( acl_get_part( aci, 4, '#', NULL ) < 0 ) {
		return 0;
	}

	/* check that the aci family is supported */
	/* FIXME: the OID is ignored? */
	if ( acl_get_part( aci, 0, '#', &bv ) < 0 ) {
		return 0;
	}

	/* check that the scope matches */
	if ( acl_get_part( aci, 1, '#', &scope ) < 0 ) {
		return 0;
	}

	/* note: scope can be either ENTRY or CHILDREN;
	 * they respectively match "entry" and "children" in bv
	 * both match "subtree" */
	switch ( asserted_scope ) {
	case SLAP_ACI_SCOPE_ENTRY:
		if ( ber_bvcmp( &scope, &aci_bv[ ACI_BV_ENTRY ] ) != 0
				&& ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_SUBTREE ] ) != 0 )
		{
			return 0;
		}
		break;

	case SLAP_ACI_SCOPE_CHILDREN:
		if ( ber_bvcmp( &scope, &aci_bv[ ACI_BV_CHILDREN ] ) != 0
				&& ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_SUBTREE ] ) != 0 )
		{
			return 0;
		}
		break;

	case SLAP_ACI_SCOPE_SUBTREE:
		/* TODO: add assertion? */
		return 0;
	}

	/* get the list of permissions clauses, bail if empty */
	if ( acl_get_part( aci, 2, '#', &perms ) <= 0 ) {
		LDAP_BUG();
		return 0;
	}

	/* check if any permissions allow desired access */
	if ( aci_list_get_rights( &perms, &desc->ad_cname, val, grant, deny ) == 0 ) {
		return 0;
	}

	/* see if we have a DN match */
	if ( acl_get_part( aci, 3, '#', &type ) < 0 ) {
		LDAP_BUG();
		return 0;
	}

	/* see if we have a public (i.e. anonymous) access */
	if ( ber_bvcmp( &aci_bv[ ACI_BV_PUBLIC ], &type ) == 0 ) {
		return 1;
	}

	/* otherwise require an identity */
	if ( BER_BVISNULL( &op->o_ndn ) || BER_BVISEMPTY( &op->o_ndn ) ) {
		return 0;
	}

	/* see if we have a users access */
	if ( ber_bvcmp( &aci_bv[ ACI_BV_USERS ], &type ) == 0 ) {
		return 1;
	}

	/* NOTE: this may fail if a DN contains a valid '#' (unescaped);
	 * just grab all the berval up to its end (ITS#3303).
	 * NOTE: the problem could be solved by providing the DN with
	 * the embedded '#' encoded as hexpairs: "cn=Foo#Bar" would
	 * become "cn=Foo\23Bar" and be safely used by aci_mask(). */
#if 0
	if ( acl_get_part( aci, 4, '#', &sdn ) < 0 ) {
		return 0;
	}
#endif
	sdn.bv_val = type.bv_val + type.bv_len + STRLENOF( "#" );
	sdn.bv_len = aci->bv_len - ( sdn.bv_val - aci->bv_val );

	/* get the type options, if any */
	if ( acl_get_part( &type, 1, '/', &opts ) > 0 ) {
		opts.bv_len = type.bv_len - ( opts.bv_val - type.bv_val );
		type.bv_len = opts.bv_val - type.bv_val - 1;

	} else {
		BER_BVZERO( &opts );
	}

	if ( ber_bvcmp( &aci_bv[ ACI_BV_ACCESS_ID ], &type ) == 0 ) {
		return dn_match( &op->o_ndn, &sdn );

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_SUBTREE ], &type ) == 0 ) {
		return dnIsSuffix( &op->o_ndn, &sdn );

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_ONELEVEL ], &type ) == 0 ) {
		struct berval pdn;

		dnParent( &sdn, &pdn );

		return dn_match( &op->o_ndn, &pdn );

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_CHILDREN ], &type ) == 0 ) {
		return ( !dn_match( &op->o_ndn, &sdn ) && dnIsSuffix( &op->o_ndn, &sdn ) );

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_SELF ], &type ) == 0 ) {
		return dn_match( &op->o_ndn, &e->e_nname );

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_DNATTR ], &type ) == 0 ) {
		Attribute		*at;
		AttributeDescription	*ad = NULL;
		const char		*text;

		rc = slap_bv2ad( &sdn, &ad, &text );
		assert( rc == LDAP_SUCCESS );

		rc = 0;
		for ( at = attrs_find( e->e_attrs, ad );
				at != NULL;
				at = attrs_find( at->a_next, ad ) )
		{
			if ( attr_valfind( at,
				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
					SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
				&op->o_ndn, NULL, op->o_tmpmemctx ) == 0 )
			{
				rc = 1;
				break;
			}
		}

		return rc;

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_GROUP ], &type ) == 0 ) {
		struct berval	oc,
				at;

		if ( BER_BVISNULL( &opts ) ) {
			oc = aci_bv[ ACI_BV_GROUP_CLASS ];
			at = aci_bv[ ACI_BV_GROUP_ATTR ];

		} else {
			if ( acl_get_part( &opts, 0, '/', &oc ) < 0 ) {
				LDAP_BUG();
			}

			if ( acl_get_part( &opts, 1, '/', &at ) < 0 ) {
				at = aci_bv[ ACI_BV_GROUP_ATTR ];
			}
		}

		if ( aci_group_member( &sdn, &oc, &at, op, e, nmatch, matches ) )
		{
			return 1;
		}

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_ROLE ], &type ) == 0 ) {
		struct berval	oc,
				at;

		if ( BER_BVISNULL( &opts ) ) {
			oc = aci_bv[ ACI_BV_ROLE_CLASS ];
			at = aci_bv[ ACI_BV_ROLE_ATTR ];

		} else {
			if ( acl_get_part( &opts, 0, '/', &oc ) < 0 ) {
				LDAP_BUG();
			}

			if ( acl_get_part( &opts, 1, '/', &at ) < 0 ) {
				at = aci_bv[ ACI_BV_ROLE_ATTR ];
			}
		}

		if ( aci_group_member( &sdn, &oc, &at, op, e, nmatch, matches ) )
		{
			return 1;
		}

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_SET ], &type ) == 0 ) {
		if ( acl_match_set( &sdn, op, e, NULL ) ) {
			return 1;
		}

	} else if ( ber_bvcmp( &aci_bv[ ACI_BV_SET_REF ], &type ) == 0 ) {
		if ( acl_match_set( &sdn, op, e, (struct berval *)&aci_bv[ ACI_BV_SET_ATTR ] ) ) {
			return 1;
		}

	} else {
		/* it passed normalization! */
		LDAP_BUG();
	}

	return 0;
}
Exemplo n.º 7
0
static int
rc_cf_gen( ConfigArgs *c )
{
	slap_overinst	*on = (slap_overinst *)c->bi;
	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;
	int		rc = ARG_BAD_CONF;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		switch( c->type ) {
		case RC_PARENT:
			if ( !BER_BVISEMPTY( &rd->rd_pdn )) {
				rc = value_add_one( &c->rvalue_vals,
						    &rd->rd_pdn );
				if ( rc == 0 ) {
					rc = value_add_one( &c->rvalue_nvals,
							    &rd->rd_npdn );
				}
				return rc;
			}
			rc = 0;
			break;

		case RC_ITEM: {
			retcode_item_t *rdi;
			int i;

			for ( rdi = rd->rd_item, i = 0; rdi; rdi = rdi->rdi_next, i++ ) {
				char buf[4096];
				struct berval bv;
				char *ptr;

				bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
				bv.bv_len += rdi->rdi_line.bv_len;
				ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
				ptr = lutil_strcopy( ptr, buf );
				ptr = lutil_strncopy( ptr, rdi->rdi_line.bv_val, rdi->rdi_line.bv_len );
				ber_bvarray_add( &c->rvalue_vals, &bv );
			}
			rc = 0;
			} break;

		default:
			LDAP_BUG();
			break;
		}

		return rc;

	} else if ( c->op == LDAP_MOD_DELETE ) {
		switch( c->type ) {
		case RC_PARENT:
			if ( rd->rd_pdn.bv_val ) {
				ber_memfree ( rd->rd_pdn.bv_val );
				rc = 0;
			}
			if ( rd->rd_npdn.bv_val ) {
				ber_memfree ( rd->rd_npdn.bv_val );
			}
			break;

		case RC_ITEM:
			if ( c->valx == -1 ) {
				retcode_item_t *rdi, *next;

				for ( rdi = rd->rd_item; rdi != NULL; rdi = next ) {
					next = rdi->rdi_next;
					retcode_item_destroy( rdi );
				}

			} else {
				retcode_item_t **rdip, *rdi;
				int i;

				for ( rdip = &rd->rd_item, i = 0; i <= c->valx && *rdip; i++, rdip = &(*rdip)->rdi_next )
					;
				if ( *rdip == NULL ) {
					return 1;
				}
				rdi = *rdip;
				*rdip = rdi->rdi_next;

				retcode_item_destroy( rdi );
			}
			rc = 0;
			break;

		default:
			LDAP_BUG();
			break;
		}
		return rc;	/* FIXME */
	}

	switch( c->type ) {
	case RC_PARENT:
		if ( rd->rd_pdn.bv_val ) {
			ber_memfree ( rd->rd_pdn.bv_val );
		}
		if ( rd->rd_npdn.bv_val ) {
			ber_memfree ( rd->rd_npdn.bv_val );
		}
		rd->rd_pdn = c->value_dn;
		rd->rd_npdn = c->value_ndn;
		rc = 0;
		break;

	case RC_ITEM: {
		retcode_item_t	rdi = { BER_BVNULL }, **rdip;
		struct berval		bv, rdn, nrdn;
		char			*next = NULL;
		int			i;

		if ( c->argc < 3 ) {
			snprintf( c->cr_msg, sizeof(c->cr_msg),
				"\"retcode-item <RDN> <retcode> [<text>]\": "
				"missing args" );
			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
				c->log, c->cr_msg );
			return ARG_BAD_CONF;
		}

		ber_str2bv( c->argv[ 1 ], 0, 0, &bv );

		rc = dnPrettyNormal( NULL, &bv, &rdn, &nrdn, NULL );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof(c->cr_msg),
				"unable to normalize RDN \"%s\": %d",
				c->argv[ 1 ], rc );
			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
				c->log, c->cr_msg );
			return ARG_BAD_CONF;
		}

		if ( !dnIsOneLevelRDN( &nrdn ) ) {
			snprintf( c->cr_msg, sizeof(c->cr_msg),
				"value \"%s\" is not a RDN",
				c->argv[ 1 ] );
			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
				c->log, c->cr_msg );
			return ARG_BAD_CONF;
		}

		if ( BER_BVISNULL( &rd->rd_npdn ) ) {
			/* FIXME: we use the database suffix */
			if ( c->be->be_nsuffix == NULL ) {
				snprintf( c->cr_msg, sizeof(c->cr_msg),
					"either \"retcode-parent\" "
					"or \"suffix\" must be defined" );
				Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
					c->log, c->cr_msg );
				return ARG_BAD_CONF;
			}

			ber_dupbv( &rd->rd_pdn, &c->be->be_suffix[ 0 ] );
			ber_dupbv( &rd->rd_npdn, &c->be->be_nsuffix[ 0 ] );
		}

		build_new_dn( &rdi.rdi_dn, &rd->rd_pdn, &rdn, NULL );
		build_new_dn( &rdi.rdi_ndn, &rd->rd_npdn, &nrdn, NULL );

		ch_free( rdn.bv_val );
		ch_free( nrdn.bv_val );

		rdi.rdi_err = strtol( c->argv[ 2 ], &next, 0 );
		if ( next == c->argv[ 2 ] || next[ 0 ] != '\0' ) {
			snprintf( c->cr_msg, sizeof(c->cr_msg),
				"unable to parse return code \"%s\"",
				c->argv[ 2 ] );
			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
				c->log, c->cr_msg );
			return ARG_BAD_CONF;
		}

		rdi.rdi_mask = SN_DG_OP_ALL;

		if ( c->argc > 3 ) {
			for ( i = 3; i < c->argc; i++ ) {
				if ( strncasecmp( c->argv[ i ], "op=", STRLENOF( "op=" ) ) == 0 )
				{
					char		**ops;
					int		j;

					ops = ldap_str2charray( &c->argv[ i ][ STRLENOF( "op=" ) ], "," );
					assert( ops != NULL );

					rdi.rdi_mask = SN_DG_OP_NONE;

					for ( j = 0; ops[ j ] != NULL; j++ ) {
						if ( strcasecmp( ops[ j ], "add" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_ADD;

						} else if ( strcasecmp( ops[ j ], "bind" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_BIND;

						} else if ( strcasecmp( ops[ j ], "compare" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_COMPARE;

						} else if ( strcasecmp( ops[ j ], "delete" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_DELETE;

						} else if ( strcasecmp( ops[ j ], "modify" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_MODIFY;

						} else if ( strcasecmp( ops[ j ], "rename" ) == 0
							|| strcasecmp( ops[ j ], "modrdn" ) == 0 )
						{
							rdi.rdi_mask |= SN_DG_OP_RENAME;

						} else if ( strcasecmp( ops[ j ], "search" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_SEARCH;

						} else if ( strcasecmp( ops[ j ], "extended" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_EXTENDED;

						} else if ( strcasecmp( ops[ j ], "auth" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_AUTH;

						} else if ( strcasecmp( ops[ j ], "read" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_READ;

						} else if ( strcasecmp( ops[ j ], "write" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_WRITE;

						} else if ( strcasecmp( ops[ j ], "all" ) == 0 ) {
							rdi.rdi_mask |= SN_DG_OP_ALL;

						} else {
							snprintf( c->cr_msg, sizeof(c->cr_msg),
								"unknown op \"%s\"",
								ops[ j ] );
							ldap_charray_free( ops );
							Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
								c->log, c->cr_msg );
							return ARG_BAD_CONF;
						}
					}

					ldap_charray_free( ops );

				} else if ( strncasecmp( c->argv[ i ], "text=", STRLENOF( "text=" ) ) == 0 )
				{
					if ( !BER_BVISNULL( &rdi.rdi_text ) ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"\"text\" already provided" );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}
					ber_str2bv( &c->argv[ i ][ STRLENOF( "text=" ) ], 0, 1, &rdi.rdi_text );

				} else if ( strncasecmp( c->argv[ i ], "matched=", STRLENOF( "matched=" ) ) == 0 )
				{
					struct berval	dn;

					if ( !BER_BVISNULL( &rdi.rdi_matched ) ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"\"matched\" already provided" );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}
					ber_str2bv( &c->argv[ i ][ STRLENOF( "matched=" ) ], 0, 0, &dn );
					if ( dnPretty( NULL, &dn, &rdi.rdi_matched, NULL ) != LDAP_SUCCESS ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"unable to prettify matched DN \"%s\"",
							&c->argv[ i ][ STRLENOF( "matched=" ) ] );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}

				} else if ( strncasecmp( c->argv[ i ], "ref=", STRLENOF( "ref=" ) ) == 0 )
				{
					char		**refs;
					int		j;

					if ( rdi.rdi_ref != NULL ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"\"ref\" already provided" );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}

					if ( rdi.rdi_err != LDAP_REFERRAL ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"providing \"ref\" "
							"along with a non-referral "
							"resultCode may cause slapd failures "
							"related to internal checks" );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
					}

					refs = ldap_str2charray( &c->argv[ i ][ STRLENOF( "ref=" ) ], " " );
					assert( refs != NULL );

					for ( j = 0; refs[ j ] != NULL; j++ ) {
						struct berval	bv;

						ber_str2bv( refs[ j ], 0, 1, &bv );
						ber_bvarray_add( &rdi.rdi_ref, &bv );
					}

					ldap_charray_free( refs );

				} else if ( strncasecmp( c->argv[ i ], "sleeptime=", STRLENOF( "sleeptime=" ) ) == 0 )
				{
					if ( rdi.rdi_sleeptime != 0 ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"\"sleeptime\" already provided" );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}

					if ( lutil_atoi( &rdi.rdi_sleeptime, &c->argv[ i ][ STRLENOF( "sleeptime=" ) ] ) ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"unable to parse \"sleeptime=%s\"",
							&c->argv[ i ][ STRLENOF( "sleeptime=" ) ] );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}

				} else if ( strncasecmp( c->argv[ i ], "unsolicited=", STRLENOF( "unsolicited=" ) ) == 0 )
				{
					char		*data;

					if ( !BER_BVISNULL( &rdi.rdi_unsolicited_oid ) ) {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"\"unsolicited\" already provided" );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}

					data = strchr( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], ':' );
					if ( data != NULL ) {
						struct berval	oid;

						if ( ldif_parse_line2( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ],
							&oid, &rdi.rdi_unsolicited_data, NULL ) )
						{
							snprintf( c->cr_msg, sizeof(c->cr_msg),
								"unable to parse \"unsolicited\"" );
							Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
								c->log, c->cr_msg );
							return ARG_BAD_CONF;
						}

						ber_dupbv( &rdi.rdi_unsolicited_oid, &oid );

					} else {
						ber_str2bv( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], 0, 1,
							&rdi.rdi_unsolicited_oid );
					}

				} else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 )
				{
					char *arg = &c->argv[ i ][ STRLENOF( "flags=" ) ];
					if ( strcasecmp( arg, "disconnect" ) == 0 ) {
						rdi.rdi_flags |= RDI_PRE_DISCONNECT;

					} else if ( strcasecmp( arg, "pre-disconnect" ) == 0 ) {
						rdi.rdi_flags |= RDI_PRE_DISCONNECT;

					} else if ( strcasecmp( arg, "post-disconnect" ) == 0 ) {
						rdi.rdi_flags |= RDI_POST_DISCONNECT;

					} else {
						snprintf( c->cr_msg, sizeof(c->cr_msg),
							"unknown flag \"%s\"", arg );
						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
							c->log, c->cr_msg );
						return ARG_BAD_CONF;
					}

				} else {
					snprintf( c->cr_msg, sizeof(c->cr_msg),
						"unknown option \"%s\"",
						c->argv[ i ] );
					Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
						c->log, c->cr_msg );
					return ARG_BAD_CONF;
				}
			}
		}

		rdi.rdi_line.bv_len = 2*(c->argc - 1) + c->argc - 2;
		for ( i = 1; i < c->argc; i++ ) {
			rdi.rdi_line.bv_len += strlen( c->argv[ i ] );
		}
		next = rdi.rdi_line.bv_val = ch_malloc( rdi.rdi_line.bv_len + 1 );

		for ( i = 1; i < c->argc; i++ ) {
			*next++ = '"';
			next = lutil_strcopy( next, c->argv[ i ] );
			*next++ = '"';
			*next++ = ' ';
		}
		*--next = '\0';

		for ( rdip = &rd->rd_item; *rdip; rdip = &(*rdip)->rdi_next )
			/* go to last */ ;


		*rdip = ( retcode_item_t * )ch_malloc( sizeof( retcode_item_t ) );
		*(*rdip) = rdi;

		rc = 0;
		} break;

	default:
		rc = SLAP_CONF_UNKNOWN;
		break;
	}

	return rc;
}
Exemplo n.º 8
0
int
modify_add_values(
	Entry		*e,
	Modification	*mod,
	int		permissive,
	const char	**text,
	char		*textbuf,
	size_t		textlen )
{
	int		rc;
	const char	*op;
	Attribute	*a;
	Modification	pmod = *mod;

	switch ( mod->sm_op ) {
	case LDAP_MOD_ADD:
		op = "add";
		break;
	case LDAP_MOD_REPLACE:
		op = "replace";
		break;
	default:
		op = "?";
		LDAP_BUG();
	}

	/* FIXME: Catch old code that doesn't set sm_numvals.
	 */
	if ( !BER_BVISNULL( &mod->sm_values[mod->sm_numvals] )) {
		unsigned i;
		for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ );
		assert( mod->sm_numvals == i );
	}

	/* check if values to add exist in attribute */
	a = attr_find( e->e_attrs, mod->sm_desc );
	if ( a != NULL ) {
		MatchingRule	*mr;
		struct berval *cvals;
		int		rc;
		unsigned i, p, flags;

		mr = mod->sm_desc->ad_type->sat_equality;
		if( mr == NULL || !mr->smr_match ) {
			/* do not allow add of additional attribute
				if no equality rule exists */
			*text = textbuf;
			snprintf( textbuf, textlen,
				"modify/%s: %s: no equality matching rule",
				op, mod->sm_desc->ad_cname.bv_val );
			return LDAP_INAPPROPRIATE_MATCHING;
		}

		if ( permissive ) {
			i = mod->sm_numvals;
			pmod.sm_values = (BerVarray)ch_malloc(
				(i + 1) * sizeof( struct berval ));
			if ( pmod.sm_nvalues != NULL ) {
				pmod.sm_nvalues = (BerVarray)ch_malloc(
					(i + 1) * sizeof( struct berval ));
			}
		}

		/* no normalization is done in this routine nor
		 * in the matching routines called by this routine.
		 * values are now normalized once on input to the
		 * server (whether from LDAP or from the underlying
		 * database).
		 */
		if ( a->a_desc == slap_schema.si_ad_objectClass ) {
			/* Needed by ITS#5517 */
			flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX;

		} else {
			flags = SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX;
		}
		if ( mod->sm_nvalues ) {
			flags |= SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
			cvals = mod->sm_nvalues;
		} else {
			cvals = mod->sm_values;
		}
		for ( p = i = 0; i < mod->sm_numvals; i++ ) {
			unsigned	slot;

			rc = attr_valfind( a, flags, &cvals[i], &slot, NULL );
			if ( rc == LDAP_SUCCESS ) {
				if ( !permissive ) {
					/* value already exists */
					*text = textbuf;
					snprintf( textbuf, textlen,
						"modify/%s: %s: value #%u already exists",
						op, mod->sm_desc->ad_cname.bv_val, i );
					return LDAP_TYPE_OR_VALUE_EXISTS;
				}
			} else if ( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
				return rc;
			}

			if ( permissive && rc ) {
				if ( pmod.sm_nvalues ) {
					pmod.sm_nvalues[p] = mod->sm_nvalues[i];
				}
				pmod.sm_values[p++] = mod->sm_values[i];
			}
		}

		if ( permissive ) {
			if ( p == 0 ) {
				/* all new values match exist */
				ch_free( pmod.sm_values );
				if ( pmod.sm_nvalues ) ch_free( pmod.sm_nvalues );
				return LDAP_SUCCESS;
			}

			BER_BVZERO( &pmod.sm_values[p] );
			if ( pmod.sm_nvalues ) {
				BER_BVZERO( &pmod.sm_nvalues[p] );
			}
		}
	}

	/* no - add them */
	if ( mod->sm_desc->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
		rc = ordered_value_add( e, mod->sm_desc, a,
			pmod.sm_values, pmod.sm_nvalues );
	} else {
		rc = attr_merge( e, mod->sm_desc, pmod.sm_values, pmod.sm_nvalues );
	}

	if ( a != NULL && permissive ) {
		ch_free( pmod.sm_values );
		if ( pmod.sm_nvalues ) ch_free( pmod.sm_nvalues );
	}

	if ( rc != 0 ) {
		/* this should return result of attr_merge */
		*text = textbuf;
		snprintf( textbuf, textlen,
			"modify/%s: %s: merge error (%d)",
			op, mod->sm_desc->ad_cname.bv_val, rc );
		return LDAP_OTHER;
	}

	return LDAP_SUCCESS;
}
Exemplo n.º 9
0
static int
meta_back_proxy_authz_bind(
	metaconn_t *mc,
	int candidate,
	Operation *op,
	SlapReply *rs,
	ldap_back_send_t sendok,
	int dolock )
{
	metainfo_t		*mi = (metainfo_t *)op->o_bd->be_private;
	metatarget_t		*mt = mi->mi_targets[ candidate ];
	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
	struct berval		binddn = BER_BVC( "" ),
				cred = BER_BVC( "" );
	int			method = LDAP_AUTH_NONE,
				rc;

	rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, sendok, &binddn, &cred, &method );
	if ( rc == LDAP_SUCCESS && !LDAP_BACK_CONN_ISBOUND( msc ) ) {
		int	msgid;

		switch ( method ) {
		case LDAP_AUTH_NONE:
		case LDAP_AUTH_SIMPLE:

			if(!dolock) {
				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
			}

			for (;;) {
				rs->sr_err = ldap_sasl_bind( msc->msc_ld,
					binddn.bv_val, LDAP_SASL_SIMPLE,
					&cred, NULL, NULL, &msgid );
				if ( rs->sr_err != LDAP_X_CONNECTING ) {
					break;
				}
				ldap_pvt_thread_yield();
			}

			if(!dolock) {
				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
			}

			rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok, dolock );
			if ( rc == LDAP_SUCCESS ) {
				/* set rebind stuff in case of successful proxyAuthz bind,
				 * so that referral chasing is attempted using the right
				 * identity */
				LDAP_BACK_CONN_ISBOUND_SET( msc );
				ber_bvreplace( &msc->msc_bound_ndn, &binddn );

				if ( META_BACK_TGT_SAVECRED( mt ) ) {
					if ( !BER_BVISNULL( &msc->msc_cred ) ) {
						memset( msc->msc_cred.bv_val, 0,
							msc->msc_cred.bv_len );
					}
					ber_bvreplace( &msc->msc_cred, &cred );
					ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );
				}
			}
			break;

		default:
			LDAP_BUG();
			break;
		}
	}

	return LDAP_BACK_CONN_ISBOUND( msc );
}
Exemplo n.º 10
0
int
bdb_bind( Operation *op, SlapReply *rs )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	Entry		*e;
	Attribute	*a;
	EntryInfo	*ei;

	AttributeDescription *password = slap_schema.si_ad_userPassword;

	DB_TXN		*rtxn;
	DB_LOCK		lock;

	Debug( LDAP_DEBUG_ARGS,
		"==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
		op->o_req_dn.bv_val);

	/* allow noauth binds */
	switch ( be_rootdn_bind( op, NULL ) ) {
	case LDAP_SUCCESS:
		/* frontend will send result */
		return rs->sr_err = LDAP_SUCCESS;

	default:
		/* give the database a chance */
		/* NOTE: this behavior departs from that of other backends,
		 * since the others, in case of password checking failure
		 * do not give the database a chance.  If an entry with
		 * rootdn's name does not exist in the database the result
		 * will be the same.  See ITS#4962 for discussion. */
		break;
	}

	rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
	switch(rs->sr_err) {
	case 0:
		break;
	default:
		rs->sr_text = "internal error";
		send_ldap_result( op, rs );
		return rs->sr_err;
	}

dn2entry_retry:
	/* get entry with reader lock */
	rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
		&lock );

	switch(rs->sr_err) {
	case DB_NOTFOUND:
	case 0:
		break;
	case LDAP_BUSY:
		send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" );
		return LDAP_BUSY;
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto dn2entry_retry;
	default:
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		return rs->sr_err;
	}

	e = ei->bei_e;
	if ( rs->sr_err == DB_NOTFOUND ) {
		if( e != NULL ) {
			bdb_cache_return_entry_r( bdb, e, &lock );
			e = NULL;
		}

		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		send_ldap_result( op, rs );

		return rs->sr_err;
	}

	ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );

	/* check for deleted */
	if ( is_entry_subentry( e ) ) {
		/* entry is an subentry, don't allow bind */
		Debug( LDAP_DEBUG_TRACE, "entry is subentry\n" );
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		goto done;
	}

	if ( is_entry_alias( e ) ) {
		/* entry is an alias, don't allow bind */
		Debug( LDAP_DEBUG_TRACE, "entry is alias\n" );
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		goto done;
	}

	if ( is_entry_referral( e ) ) {
		Debug( LDAP_DEBUG_TRACE, "entry is referral\n" );
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		goto done;
	}

	switch ( op->oq_bind.rb_method ) {
	case LDAP_AUTH_SIMPLE:
		a = attr_find( e->e_attrs, password );
		if ( a == NULL ) {
			rs->sr_err = LDAP_INVALID_CREDENTIALS;
			goto done;
		}

		if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
					&rs->sr_text ) != 0 )
		{
			/* failure; stop front end from sending result */
			rs->sr_err = LDAP_INVALID_CREDENTIALS;
			goto done;
		}

		rs->sr_err = 0;
		break;

	default:
		LDAP_BUG(); /* should not be reachable */
		rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
		rs->sr_text = "authentication method not supported";
	}

done:
	/* free entry and reader lock */
	if( e != NULL ) {
		bdb_cache_return_entry_r( bdb, e, &lock );
	}

	if ( rs->sr_err ) {
		send_ldap_result( op, rs );
		rs_send_cleanup( rs );
	}
	/* front end will send result on success (rs->sr_err==0) */
	return rs->sr_err;
}
Exemplo n.º 11
0
static int
dds_op_modify( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
	dds_info_t	*di = (dds_info_t *)on->on_bi.bi_private;
	Modifications	*mod;
	Entry		*e = NULL;
	BackendInfo	*bi = op->o_bd->bd_info;
	int		was_dynamicObject = 0,
			is_dynamicObject = 0;
	struct berval	bv_entryTtl = BER_BVNULL;
	time_t		entryTtl = 0;
	char		textbuf[ SLAP_TEXT_BUFLEN ];

	if ( DDS_OFF( di ) ) {
		return SLAP_CB_CONTINUE;
	}

	/* bv_entryTtl stores the string representation of the entryTtl
	 * across modifies for consistency checks of the final value;
	 * the bv_val points to a static buffer; the bv_len is zero when
	 * the attribute is deleted.
	 * entryTtl stores the integer representation of the entryTtl;
	 * its value is -1 when the attribute is deleted; it is 0 only
	 * if no modifications of the entryTtl occurred, as an entryTtl
	 * of 0 is invalid. */
	bv_entryTtl.bv_val = textbuf;

	op->o_bd->bd_info = (BackendInfo *)on->on_info;
	rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn,
		slap_schema.si_oc_dynamicObject, slap_schema.si_ad_entryTtl, 0, &e );
	if ( rs->sr_err == LDAP_SUCCESS && e != NULL ) {
		Attribute	*a = attr_find( e->e_attrs, slap_schema.si_ad_entryTtl );

		/* the value of the entryTtl is saved for later checks */
		if ( a != NULL ) {
			unsigned long	ttl;
			int		rc;

			bv_entryTtl.bv_len = a->a_nvals[ 0 ].bv_len;
			memcpy( bv_entryTtl.bv_val, a->a_nvals[ 0 ].bv_val, bv_entryTtl.bv_len );
			bv_entryTtl.bv_val[ bv_entryTtl.bv_len ] = '\0';
			rc = lutil_atoul( &ttl, bv_entryTtl.bv_val );
			assert( rc == 0 );
			entryTtl = (time_t)ttl;
		}

		be_entry_release_r( op, e );
		e = NULL;
		was_dynamicObject = is_dynamicObject = 1;
	}
	op->o_bd->bd_info = bi;

	rs->sr_err = LDAP_SUCCESS;
	for ( mod = op->orm_modlist; mod; mod = mod->sml_next ) {
		if ( mod->sml_desc == slap_schema.si_ad_objectClass ) {
			int		i;
			ObjectClass	*oc;

			switch ( mod->sml_op ) {
			case LDAP_MOD_DELETE:
				if ( mod->sml_values == NULL ) {
					is_dynamicObject = 0;
					break;
				}

				for ( i = 0; !BER_BVISNULL( &mod->sml_values[ i ] ); i++ ) {
					oc = oc_bvfind( &mod->sml_values[ i ] );
					if ( oc == slap_schema.si_oc_dynamicObject ) {
						is_dynamicObject = 0;
						break;
					}
				}

				break;

			case LDAP_MOD_REPLACE:
				if ( mod->sml_values == NULL ) {
					is_dynamicObject = 0;
					break;
				}
				/* fallthru */

			case LDAP_MOD_ADD:
				for ( i = 0; !BER_BVISNULL( &mod->sml_values[ i ] ); i++ ) {
					oc = oc_bvfind( &mod->sml_values[ i ] );
					if ( oc == slap_schema.si_oc_dynamicObject ) {
						is_dynamicObject = 1;
						break;
					}
				}
				break;
			}

		} else if ( mod->sml_desc == slap_schema.si_ad_entryTtl ) {
			unsigned long	uttl;
			time_t		ttl;
			int		rc;

			switch ( mod->sml_op ) {
			case LDAP_MOD_DELETE:
			case SLAP_MOD_SOFTDEL: /* FIXME? */
				if ( mod->sml_values != NULL ) {
					if ( BER_BVISEMPTY( &bv_entryTtl )
						|| !bvmatch( &bv_entryTtl, &mod->sml_values[ 0 ] ) )
					{
						rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
							slap_schema.si_ad_entry, NULL, ACL_DISCLOSE );
						if ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) {
							rs->sr_err = LDAP_NO_SUCH_OBJECT;

						} else {
							rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE;
						}
						goto done;
					}
				}
				bv_entryTtl.bv_len = 0;
				entryTtl = -1;
				break;

			case LDAP_MOD_REPLACE:
				bv_entryTtl.bv_len = 0;
				entryTtl = -1;
				/* fallthru */

			case LDAP_MOD_ADD:
			case SLAP_MOD_SOFTADD: /* FIXME? */
			case SLAP_MOD_ADD_IF_NOT_PRESENT: /* FIXME? */
				assert( mod->sml_values != NULL );
				assert( BER_BVISNULL( &mod->sml_values[ 1 ] ) );

				if ( !BER_BVISEMPTY( &bv_entryTtl ) ) {
					rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
						slap_schema.si_ad_entry, NULL, ACL_DISCLOSE );
					if ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) {
						rs->sr_err = LDAP_NO_SUCH_OBJECT;

					} else {
						rs->sr_text = "attribute 'entryTtl' cannot have multiple values";
						rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
					}
					goto done;
				}

				rc = lutil_atoul( &uttl, mod->sml_values[ 0 ].bv_val );
				ttl = (time_t)uttl;
				assert( rc == 0 );
				if ( ttl > DDS_RF2589_MAX_TTL ) {
					rs->sr_err = LDAP_PROTOCOL_ERROR;
					rs->sr_text = "invalid time-to-live for dynamicObject";
					goto done;
				}

				if ( ttl <= 0 || ttl > di->di_max_ttl ) {
					/* FIXME: I don't understand if this has to be an error,
					 * or an indication that the requested Ttl has been
					 * shortened to di->di_max_ttl >= 1 day */
					rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
					rs->sr_text = "time-to-live for dynamicObject exceeds administrative limit";
					goto done;
				}

				entryTtl = ttl;
				bv_entryTtl.bv_len = mod->sml_values[ 0 ].bv_len;
				memcpy( bv_entryTtl.bv_val, mod->sml_values[ 0 ].bv_val, bv_entryTtl.bv_len );
				bv_entryTtl.bv_val[ bv_entryTtl.bv_len ] = '\0';
				break;

			case LDAP_MOD_INCREMENT:
				if ( BER_BVISEMPTY( &bv_entryTtl ) ) {
					rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
						slap_schema.si_ad_entry, NULL, ACL_DISCLOSE );
					if ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) {
						rs->sr_err = LDAP_NO_SUCH_OBJECT;

					} else {
						rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE;
						rs->sr_text = "modify/increment: entryTtl: no such attribute";
					}
					goto done;
				}

				entryTtl++;
				if ( entryTtl > DDS_RF2589_MAX_TTL ) {
					rs->sr_err = LDAP_PROTOCOL_ERROR;
					rs->sr_text = "invalid time-to-live for dynamicObject";

				} else if ( entryTtl <= 0 || entryTtl > di->di_max_ttl ) {
					/* FIXME: I don't understand if this has to be an error,
					 * or an indication that the requested Ttl has been
					 * shortened to di->di_max_ttl >= 1 day */
					rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
					rs->sr_text = "time-to-live for dynamicObject exceeds administrative limit";
				}

				if ( rs->sr_err != LDAP_SUCCESS ) {
					rc = backend_attribute( op, NULL, &op->o_req_ndn,
						slap_schema.si_ad_entry, NULL, ACL_DISCLOSE );
					if ( rc == LDAP_INSUFFICIENT_ACCESS ) {
						rs->sr_text = NULL;
						rs->sr_err = LDAP_NO_SUCH_OBJECT;

					}
					goto done;
				}

				bv_entryTtl.bv_len = snprintf( textbuf, sizeof( textbuf ), "%ld", entryTtl );
				break;

			default:
				LDAP_BUG();
				break;
			}

		} else if ( mod->sml_desc == ad_entryExpireTimestamp ) {
			/* should have been trapped earlier */
			assert( mod->sml_flags & SLAP_MOD_INTERNAL );
		}
	}

done:;
	if ( rs->sr_err == LDAP_SUCCESS ) {
		int	rc;

		/* FIXME: this could be allowed when the Relax control is used...
		 * in that case:
		 *
		 * TODO
		 *
		 *	static => dynamic:
		 *		entryTtl must be provided; add
		 *		entryExpireTimestamp accordingly
		 *
		 *	dynamic => static:
		 *		entryTtl must be removed; remove
		 *		entryTimestamp accordingly
		 *
		 * ... but we need to make sure that there are no subordinate
		 * issues...
		 */
		rc = is_dynamicObject - was_dynamicObject;
		if ( rc ) {
#if 0 /* fix subordinate issues first */
			if ( get_relax( op ) ) {
				switch ( rc ) {
				case -1:
					/* need to delete entryTtl to have a consistent entry */
					if ( entryTtl != -1 ) {
						rs->sr_text = "objectClass modification from dynamicObject to static entry requires entryTtl deletion";
						rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
					}
					break;

				case 1:
					/* need to add entryTtl to have a consistent entry */
					if ( entryTtl <= 0 ) {
						rs->sr_text = "objectClass modification from static entry to dynamicObject requires entryTtl addition";
						rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
					}
					break;
				}

			} else
#endif
			{
				switch ( rc ) {
				case -1:
					rs->sr_text = "objectClass modification cannot turn dynamicObject into static entry";
					break;

				case 1:
					rs->sr_text = "objectClass modification cannot turn static entry into dynamicObject";
					break;
				}
				rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
			}

			if ( rc != LDAP_SUCCESS ) {
				rc = backend_attribute( op, NULL, &op->o_req_ndn,
					slap_schema.si_ad_entry, NULL, ACL_DISCLOSE );
				if ( rc == LDAP_INSUFFICIENT_ACCESS ) {
					rs->sr_text = NULL;
					rs->sr_err = LDAP_NO_SUCH_OBJECT;
				}
			}
		}
	}

	if ( rs->sr_err == LDAP_SUCCESS && entryTtl != 0 ) {
		Modifications	*tmpmod = NULL, **modp;

		for ( modp = &op->orm_modlist; *modp; modp = &(*modp)->sml_next )
			;

		tmpmod = ch_calloc( 1, sizeof( Modifications ) );
		tmpmod->sml_flags = SLAP_MOD_INTERNAL;
		tmpmod->sml_type = ad_entryExpireTimestamp->ad_cname;
		tmpmod->sml_desc = ad_entryExpireTimestamp;

		*modp = tmpmod;

		if ( entryTtl == -1 ) {
			/* delete entryExpireTimestamp */
			tmpmod->sml_op = LDAP_MOD_DELETE;

		} else {
			time_t		expire;
			char		tsbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
			struct berval	bv;

			/* keep entryExpireTimestamp consistent
			 * with entryTtl */
			expire = slap_get_time() + entryTtl;
			bv.bv_val = tsbuf;
			bv.bv_len = sizeof( tsbuf );
			slap_timestamp( &expire, &bv );

			tmpmod->sml_op = LDAP_MOD_REPLACE;
			value_add_one( &tmpmod->sml_values, &bv );
			value_add_one( &tmpmod->sml_nvalues, &bv );
			tmpmod->sml_numvals = 1;
		}
	}

	if ( rs->sr_err ) {
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
		send_ldap_result( op, rs );
		return rs->sr_err;
	}

	return SLAP_CB_CONTINUE;
}
Exemplo n.º 12
0
struct berbuf *
backsql_strfcat_x( struct berbuf *dest, void *memctx, const char *fmt, ... )
{
	va_list		strs;
	ber_len_t	cdlen;

	assert( dest != NULL );
	assert( fmt != NULL );
	assert( dest->bb_len == 0 || dest->bb_len > dest->bb_val.bv_len );
	assert( dest->bb_val.bv_val == NULL
			|| dest->bb_val.bv_len == strlen( dest->bb_val.bv_val ) );

#ifdef BACKSQL_TRACE
	Debug( LDAP_DEBUG_TRACE, "==>backsql_strfcat()\n" );
#endif /* BACKSQL_TRACE */

	va_start( strs, fmt );
	if ( dest->bb_val.bv_val == NULL || dest->bb_len == 0 ) {
		dest->bb_val.bv_val = (char *)ber_memalloc_x( BACKSQL_STR_GROW * sizeof( char ), memctx );
		dest->bb_val.bv_len = 0;
		dest->bb_len = BACKSQL_STR_GROW;
	}

	cdlen = dest->bb_val.bv_len;
	for ( ; fmt[0]; fmt++ ) {
		ber_len_t	cslen, grow;
		char		*cstr, cc[ 2 ] = { '\0', '\0' };
		struct berval	*cbv;

		switch ( fmt[ 0 ] ) {

		/* berval */
		case 'b':
			cbv = va_arg( strs, struct berval * );
			cstr = cbv->bv_val;
			cslen = cbv->bv_len;
			break;

		/* length + string */
		case 'l':
			cslen = va_arg( strs, ber_len_t );
			cstr = va_arg( strs, char * );
			break;

		/* string */
		case 's':
			cstr = va_arg( strs, char * );
			cslen = strlen( cstr );
			break;

		/* char */
		case 'c':
			/*
			 * `char' is promoted to `int' when passed through `...'
			 */
			cc[0] = va_arg( strs, int );
			cstr = cc;
			cslen = 1;
			break;

		default:
			LDAP_BUG();
		}

		grow = BACKSQL_MAX( BACKSQL_STR_GROW, cslen );
		if ( dest->bb_len - cdlen <= cslen ) {
			char	*tmp_dest;

#ifdef BACKSQL_TRACE
			Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): "
				"buflen=%d, cdlen=%d, cslen=%d "
				"-- reallocating dest\n",
				dest->bb_len, cdlen + 1, cslen );
#endif /* BACKSQL_TRACE */

			tmp_dest = (char *)ber_memrealloc_x( dest->bb_val.bv_val,
					( dest->bb_len ) + grow * sizeof( char ), memctx );
			if ( tmp_dest == NULL ) {
				Debug( LDAP_DEBUG_ANY, "backsql_strfcat(): "
					"could not reallocate string buffer.\n" );
				va_end( strs );
				return NULL;
			}
			dest->bb_val.bv_val = tmp_dest;
			dest->bb_len += grow * sizeof( char );

#ifdef BACKSQL_TRACE
			Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): "
				"new buflen=%d, dest=%p\n", dest->bb_len, dest );
#endif /* BACKSQL_TRACE */
		}

		assert( cstr != NULL );

		memcpy( dest->bb_val.bv_val + cdlen, cstr, cslen + 1 );
		cdlen += cslen;
	}

	va_end( strs );

#ifdef BACKSQL_TRACE
	Debug( LDAP_DEBUG_TRACE, "<==backsql_strfcat() (dest=\"%s\")\n",
			dest->bb_val.bv_val );
#endif /* BACKSQL_TRACE */

	dest->bb_val.bv_len = cdlen;

	return dest;
}
Exemplo n.º 13
0
int
frontend_init( void )
{
	/* data */
	frontendDB = &slap_frontendDB;
	frontendDB->bd_self = frontendDB;

	/* biglock */
	slap_biglock_init(frontendDB);

	/* ACLs */
	frontendDB->be_dfltaccess = ACL_READ;

	/* limits */
	frontendDB->be_def_limit.lms_t_soft = SLAPD_DEFAULT_TIMELIMIT;	/* backward compatible limits */
	frontendDB->be_def_limit.lms_t_hard = 0;
	frontendDB->be_def_limit.lms_s_soft = SLAPD_DEFAULT_SIZELIMIT;	/* backward compatible limits */
	frontendDB->be_def_limit.lms_s_hard = 0;
	frontendDB->be_def_limit.lms_s_unchecked = -1;			/* no limit on unchecked size */
	frontendDB->be_def_limit.lms_s_pr = 0;				/* page limit */
	frontendDB->be_def_limit.lms_s_pr_hide = 0;			/* don't hide number of entries left */
	frontendDB->be_def_limit.lms_s_pr_total = 0;			/* number of total entries returned by pagedResults equal to hard limit */

	ldap_pvt_thread_mutex_init( &frontendDB->be_pcl_mutex );

	/* suffix */
	frontendDB->be_suffix = ch_calloc( 2, sizeof( struct berval ) );
	ber_str2bv( "", 0, 1, &frontendDB->be_suffix[0] );
	BER_BVZERO( &frontendDB->be_suffix[1] );
	frontendDB->be_nsuffix = ch_calloc( 2, sizeof( struct berval ) );
	ber_str2bv( "", 0, 1, &frontendDB->be_nsuffix[0] );
	BER_BVZERO( &frontendDB->be_nsuffix[1] );

	/* info */
	frontendDB->bd_info = &slap_frontendInfo;

	SLAP_BFLAGS(frontendDB) |= SLAP_BFLAG_FRONTEND;

	/* name */
	frontendDB->bd_info->bi_type = "frontend";

	/* known controls */
	{
		int	i;

		frontendDB->bd_info->bi_controls = slap_known_controls;

		for ( i = 0; slap_known_controls[ i ]; i++ ) {
			int	cid;

			if ( slap_find_control_id( slap_known_controls[ i ], &cid )
					== LDAP_CONTROL_NOT_FOUND )
			{
				LDAP_BUG();
				return -1;
			}

			frontendDB->bd_info->bi_ctrls[ cid ] = 1;
			frontendDB->be_ctrls[ cid ] = 1;
		}
	}

	/* calls */
	frontendDB->bd_info->bi_op_abandon = fe_op_abandon;
	frontendDB->bd_info->bi_op_add = fe_op_add;
	frontendDB->bd_info->bi_op_bind = fe_op_bind;
	frontendDB->bd_info->bi_op_compare = fe_op_compare;
	frontendDB->bd_info->bi_op_delete = fe_op_delete;
	frontendDB->bd_info->bi_op_modify = fe_op_modify;
	frontendDB->bd_info->bi_op_modrdn = fe_op_modrdn;
	frontendDB->bd_info->bi_op_search = fe_op_search;
	frontendDB->bd_info->bi_extended = fe_extended;
	frontendDB->bd_info->bi_operational = fe_aux_operational;
	frontendDB->bd_info->bi_entry_get_rw = fe_entry_get_rw;
	frontendDB->bd_info->bi_entry_release_rw = fe_entry_release_rw;
	frontendDB->bd_info->bi_access_allowed = fe_access_allowed;
	frontendDB->bd_info->bi_acl_group = fe_acl_group;
	frontendDB->bd_info->bi_acl_attribute = fe_acl_attribute;

#if 0
	/* FIXME: is this too early? */
	return backend_startup_one( frontendDB );
#endif

	return 0;
}
Exemplo n.º 14
0
static int
monitor_subsys_rww_update(
	Operation		*op,
	SlapReply		*rs,
	Entry                   *e )
{
	monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private;
	Connection	*c;
	ber_socket_t	connindex;
	long		nconns, nwritewaiters, nreadwaiters;

	int		i;
	struct berval	nrdn;

	Attribute	*a;
	char 		buf[LDAP_PVT_INTTYPE_CHARS(long)];
	long		num = 0;
	ber_len_t	len;

	assert( mi != NULL );
	assert( e != NULL );

	dnRdn( &e->e_nname, &nrdn );

	for ( i = 0; !BER_BVISNULL( &monitor_rww[ i ].nrdn ); i++ ) {
		if ( dn_match( &nrdn, &monitor_rww[ i ].nrdn ) ) {
			break;
		}
	}

	if ( i == MONITOR_RWW_LAST ) {
		return SLAP_CB_CONTINUE;
	}

	nconns = nwritewaiters = nreadwaiters = 0;
	for ( c = connection_first( &connindex );
			c != NULL;
			c = connection_next( c, &connindex ), nconns++ )
	{
		if ( c->c_writewaiter ) {
			nwritewaiters++;
		}

		/* FIXME: ?!? */
		if ( c->c_currentber != NULL ) {
			nreadwaiters++;
		}
	}
	connection_done(c);

	switch ( i ) {
	case MONITOR_RWW_READ:
		num = nreadwaiters;
		break;

	case MONITOR_RWW_WRITE:
		num = nwritewaiters;
		break;

	default:
		LDAP_BUG();
	}

	snprintf( buf, sizeof( buf ), "%ld", num );

	a = attr_find( e->e_attrs, mi->mi_ad_monitorCounter );
	assert( a != NULL );
	len = strlen( buf );
	if ( len > a->a_vals[ 0 ].bv_len ) {
		a->a_vals[ 0 ].bv_val = ber_memrealloc( a->a_vals[ 0 ].bv_val, len + 1 );
		if ( BER_BVISNULL( &a->a_vals[ 0 ] ) ) {
			BER_BVZERO( &a->a_vals[ 0 ] );
			return SLAP_CB_CONTINUE;
		}
	}
	memcpy( a->a_vals[ 0 ].bv_val, buf, len + 1 );
	a->a_vals[ 0 ].bv_len = len;

	/* FIXME: touch modifyTimestamp? */

	return SLAP_CB_CONTINUE;
}