Exemplo n.º 1
0
static int
pg_dynacl_unparse(
	void		*priv,
	struct berval	*bv )
{
	pg_t		*pg = (pg_t *)priv;
	char		*ptr;

	bv->bv_len = STRLENOF( " dynacl/posixGroup.expand=" ) + pg->pg_pat.bv_len;
	bv->bv_val = ch_malloc( bv->bv_len + 1 );

	ptr = lutil_strcopy( bv->bv_val, " dynacl/posixGroup" );

	switch ( pg->pg_style ) {
	case ACL_STYLE_BASE:
		ptr = lutil_strcopy( ptr, ".exact=" );
		break;

	case ACL_STYLE_EXPAND:
		ptr = lutil_strcopy( ptr, ".expand=" );
		break;

	default:
		assert( 0 );
	}

	ptr = lutil_strncopy( ptr, pg->pg_pat.bv_val, pg->pg_pat.bv_len );
	ptr[ 0 ] = '\0';

	bv->bv_len = ptr - bv->bv_val;

	return 0;
}
Exemplo n.º 2
0
static void ERR (char * const argv[], const char * s, char c)
{
#ifdef DF_TRACE_DEBUG
printf("DF_TRACE_DEBUG: 	static void ERR () in getopt.c\n");
#endif
	if (opterr)
	{
		char *ptr, outbuf[4096];

		ptr = lutil_strncopy(outbuf, argv[0], sizeof(outbuf) - 2);
		ptr = lutil_strncopy(ptr, s, sizeof(outbuf)-2 -(ptr-outbuf));
		*ptr++ = c;
		*ptr++ = '\n';
#ifdef HAVE_EBCDIC
		__atoe_l(outbuf, ptr - outbuf);
#endif
		(void) write(STDERR_FILENO,outbuf,ptr - outbuf);
	}
}
Exemplo n.º 3
0
/* The __LIBASCII doesn't include a working vsprintf, so we make do
 * using just sprintf. This is a very simplistic parser that looks for
 * format strings and uses sprintf to process them one at a time.
 * Literal text is just copied straight to the destination.
 * The result is appended to the destination string. The parser
 * recognizes field-width specifiers and the 'l' qualifier; it
 * may need to be extended to recognize other qualifiers but so
 * far this seems to be enough.
 */
int ber_pvt_vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
{
	char *ptr, *pct, *s2, *f2, *end;
	char fm2[64];
	int len, rem;

	ptr = (char *)fmt;
	s2 = str;
	fm2[0] = '%';
	if (n) {
		end = str + n;
	} else {
		end = NULL;
	}

	for (pct = strchr(ptr, '%'); pct; pct = strchr(ptr, '%')) {
		len = pct-ptr;
		if (end) {
			rem = end-s2;
			if (rem < 1) return -1;
			if (rem < len) len = rem;
		}
		s2 = lutil_strncopy( s2, ptr, len );
		/* Did we cheat the length above? If so, bail out */
		if (len < pct-ptr) return -1;
		for (pct++, f2 = fm2+1; isdigit(*pct);) *f2++ = *pct++;
		if (*pct == 'l') *f2++ = *pct++;
		if (*pct == '%') {
			*s2++ = '%';
		} else {
			*f2++ = *pct;
			*f2 = '\0';
			if (*pct == 's') {
				char *ss = va_arg(ap, char *);
				/* Attempt to limit sprintf output. This
				 * may be thrown off if field widths were
				 * specified for this string.
				 *
				 * If it looks like the string is too
				 * long for the remaining buffer, bypass
				 * sprintf and just copy what fits, then
				 * quit.
				 */
				if (end && strlen(ss) > (rem=end-s2)) {
					strncpy(s2, ss, rem);
					return -1;
				} else {
					s2 += sprintf(s2, fm2, ss);
				}
			} else {
				s2 += sprintf(s2, fm2, va_arg(ap, int));
			}
		}
Exemplo n.º 4
0
static int
gssattr_dynacl_unparse(
	void		*priv,
	struct berval	*bv )
{
	gssattr_t	*gssattr = (gssattr_t *)priv;
	char		*ptr;

	bv->bv_len = STRLENOF( " dynacl/gss/.expand=" ) +
		     gssattr->gssattr_name.bv_len +
		     gssattr->gssattr_value.bv_len;
	bv->bv_val = ch_malloc( bv->bv_len + 1 );

	ptr = lutil_strcopy( bv->bv_val, " dynacl/gss/" );
	ptr = lutil_strncopy( ptr, gssattr->gssattr_name.bv_val,
			      gssattr->gssattr_name.bv_len );
	switch ( gssattr->gssattr_style ) {
	case ACL_STYLE_BASE:
		ptr = lutil_strcopy( ptr, ".exact=" );
		break;
	case ACL_STYLE_REGEX:
		ptr = lutil_strcopy( ptr, ".regex=" );
		break;
	case ACL_STYLE_EXPAND:
		ptr = lutil_strcopy( ptr, ".expand=" );
		break;
	default:
		assert( 0 );
		break;
	}

	ptr = lutil_strncopy( ptr, gssattr->gssattr_value.bv_val,
			      gssattr->gssattr_value.bv_len );

	ptr[ 0 ] = '\0';

	bv->bv_len = ptr - bv->bv_val;

	return 0;
}
Exemplo n.º 5
0
static int
rdnval_repair_cb( Operation *op, SlapReply *rs )
{
	int rc;
	rdnval_repair_cb_t *rcb = op->o_callback->sc_private;
	rdnval_mod_t *mod;
	BerVarray vals = NULL, nvals = NULL;
	int numvals = 0;
	ber_len_t len;
	BackendDB *save_bd = op->o_bd;

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

	case REP_SEARCHREF:
	case REP_RESULT:
		return rs->sr_err;

	default:
		assert( 0 );
	}

	assert( rs->sr_entry != NULL );

	op->o_bd = rcb->bd;
	rc = rdnval_rdn2vals( op, rs, &rs->sr_entry->e_name, &rs->sr_entry->e_nname,
		&vals, &nvals, &numvals );
	op->o_bd = save_bd;
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	len = sizeof( rdnval_mod_t ) + rs->sr_entry->e_nname.bv_len + 1;
	mod = op->o_tmpalloc( len, op->o_tmpmemctx );
	mod->ndn.bv_len = rs->sr_entry->e_nname.bv_len;
	mod->ndn.bv_val = (char *)&mod[1];
	lutil_strncopy( mod->ndn.bv_val, rs->sr_entry->e_nname.bv_val, rs->sr_entry->e_nname.bv_len );
	mod->vals = vals;
	mod->nvals = nvals;
	mod->numvals = numvals;

	mod->next = rcb->mods;
	rcb->mods = mod;

	Debug( LDAP_DEBUG_TRACE, "%s: rdnval_repair_cb: scheduling entry DN=\"%s\" for repair\n",
		op->o_log_prefix, rs->sr_entry->e_name.bv_val, 0 );

	return 0;
}
Exemplo n.º 6
0
ID ndb_tool_entry_next(
	BackendDB *be )
{
	struct ndb_info *ni = (struct ndb_info *) be->be_private;
	char *ptr;
	ID id;
	int i;

	assert( be != NULL );
	assert( slapMode & SLAP_TOOL_MODE );

	if ( myScanOp->nextResult() ) {
		myScanOp->close();
		myScanOp = NULL;
		myScanTxn->close();
		myScanTxn = NULL;
		return NOID;
	}
	id = myScanID->u_64_value();

	if ( myOcList ) {
		ber_bvarray_free( myOcList );
	}
	myOcList = ndb_ref2oclist( myOcbuf, NULL );
	for ( i=0; i<NDB_MAX_RDNS; i++ ) {
		if ( myScanDN[i]->isNULL() || !myRdns.nr_buf[i][0] )
			break;
	}
	myRdns.nr_num = i;
	ptr = myDNbuf;
	for ( --i; i>=0; i-- ) {
		char *buf;
		int len;
		buf = myRdns.nr_buf[i];
		len = *buf++;
		ptr = lutil_strncopy( ptr, buf, len );
		if ( i )
			*ptr++ = ',';
	}
	*ptr = '\0';
	myDn.bv_val = myDNbuf;
	myDn.bv_len = ptr - myDNbuf;

	return id;
}
Exemplo n.º 7
0
static int idattr_dynacl_unparse(
    void		*priv,
    struct berval	*bv )
{
    idattr_t		*id = (idattr_t *)priv;
    char		*ptr = NULL, *start = NULL;
    size_t len = 0;
    bv->bv_len = MAX_ACE_LEN;
    bv->bv_val = ch_calloc( 1, bv->bv_len + 1 );

    start = ptr = lutil_strcopy( bv->bv_val, " dynacl/idattr" );

    if (idattr_dynacl_unparse_optionsavailable(id, &ptr) != 0)
        goto exit_on_error;

    if (idattr_dynacl_unparse_operation(id, &ptr) != 0)
        goto exit_on_error;
    if (idattr_dynacl_unparse_applyto(id, &ptr) != 0)
        goto exit_on_error;
    if (idattr_dynacl_unparse_selfattr(id, &ptr) != 0)
        goto exit_on_error;
    if (idattr_dynacl_unparse_boolattr(id, &ptr) != 0)
        goto exit_on_error;

    // remove trailing option terminator
    len = strlen(start);
    if (len && start[len - 1] == ';') {
        start[len - 1] = '\0';
        ptr = start + len - 1;
    }

    if (idattr_dynacl_unparse_style(id, &ptr) != 0)
        goto exit_on_error;

    ptr = lutil_strncopy( ptr, id->idattr_pat.bv_val, id->idattr_pat.bv_len );
    ptr[ 0 ] = '\0';

    bv->bv_len = ptr - bv->bv_val;

exit_on_error:
    return 0;
}
Exemplo n.º 8
0
void
build_new_dn( struct berval * new_dn,
	struct berval * parent_dn,
	struct berval * newrdn,
	void *memctx )
{
	char *ptr;

	if ( parent_dn == NULL || parent_dn->bv_len == 0 ) {
		ber_dupbv_x( new_dn, newrdn, memctx );
		return;
	}

	new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
	new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx );

	ptr = lutil_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len );
	*ptr++ = ',';
	strcpy( ptr, parent_dn->bv_val );
}
Exemplo n.º 9
0
static char *
rwm_suffix_massage_regexize( const char *s )
{
	char *res, *ptr;
	const char *p, *r;
	int i;

	if ( s[0] == '\0' ) {
		return ch_strdup( "^(.+)$" );
	}

	for ( i = 0, p = s; 
			( r = strchr( p, ',' ) ) != NULL; 
			p = r + 1, i++ )
		;

	res = ch_calloc( sizeof( char ), strlen( s )
			+ STRLENOF( "((.+),)?" )
			+ STRLENOF( "[ ]?" ) * i
			+ STRLENOF( "$" ) + 1 );

	ptr = lutil_strcopy( res, "((.+),)?" );
	for ( i = 0, p = s;
			( r = strchr( p, ',' ) ) != NULL;
			p = r + 1 , i++ ) {
		ptr = lutil_strncopy( ptr, p, r - p + 1 );
		ptr = lutil_strcopy( ptr, "[ ]?" );

		if ( r[ 1 ] == ' ' ) {
			r++;
		}
	}
	ptr = lutil_strcopy( ptr, p );
	ptr[0] = '$';
	ptr[1] = '\0';

	return res;
}
Exemplo n.º 10
0
static int
vernum_repair_cb( Operation *op, SlapReply *rs )
{
	int rc;
	vernum_repair_cb_t *rcb = op->o_callback->sc_private;
	vernum_mod_t *mod;
	ber_len_t len;
	BackendDB *save_bd = op->o_bd;

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

	case REP_SEARCHREF:
	case REP_RESULT:
		return rs->sr_err;

	default:
		assert( 0 );
	}

	assert( rs->sr_entry != NULL );

	len = sizeof( vernum_mod_t ) + rs->sr_entry->e_nname.bv_len + 1;
	mod = op->o_tmpalloc( len, op->o_tmpmemctx );
	mod->ndn.bv_len = rs->sr_entry->e_nname.bv_len;
	mod->ndn.bv_val = (char *)&mod[1];
	lutil_strncopy( mod->ndn.bv_val, rs->sr_entry->e_nname.bv_val, rs->sr_entry->e_nname.bv_len );

	mod->next = rcb->mods;
	rcb->mods = mod;

	Debug( LDAP_DEBUG_TRACE, "%s: vernum_repair_cb: scheduling entry DN=\"%s\" for repair\n",
		op->o_log_prefix, rs->sr_entry->e_name.bv_val, 0 );

	return 0;
}
Exemplo n.º 11
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.º 12
0
static int
rdnval_unique_check( Operation *op, BerVarray vals )
{
	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;

	BackendDB db = *op->o_bd;
	Operation op2 = *op;
	SlapReply rs2 = { 0 };
	int i;
	BerVarray fvals;
	char *ptr;
	int gotit = 0;
	slap_callback cb = { 0 };

	/* short-circuit attempts to add suffix entry */
	if ( op->o_tag == LDAP_REQ_ADD
		&& be_issuffix( op->o_bd, &op->o_req_ndn ) )
	{
		return LDAP_SUCCESS;
	}

	op2.o_bd = &db;
	op2.o_bd->bd_info = (BackendInfo *)on->on_info;
	op2.o_tag = LDAP_REQ_SEARCH;
	op2.o_dn = op->o_bd->be_rootdn;
	op2.o_ndn = op->o_bd->be_rootndn;
	op2.o_callback = &cb;
	cb.sc_response = rdnval_unique_check_cb;
	cb.sc_private = (void *)&gotit;

	dnParent( &op->o_req_ndn, &op2.o_req_dn );
	op2.o_req_ndn = op2.o_req_dn;

	op2.ors_limit = NULL;
	op2.ors_slimit = 1;
	op2.ors_tlimit = SLAP_NO_LIMIT;
	op2.ors_attrs = slap_anlist_no_attrs;
	op2.ors_attrsonly = 1;
	op2.ors_deref = LDAP_DEREF_NEVER;
	op2.ors_scope = LDAP_SCOPE_ONELEVEL;

	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ )
		/* just count */ ;

	fvals = op->o_tmpcalloc( sizeof( struct berval ), i + 1,
		op->o_tmpmemctx );

	op2.ors_filterstr.bv_len = 0;
	if ( i > 1 ) {
		op2.ors_filterstr.bv_len = STRLENOF( "(&)" );
	}

	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
		ldap_bv2escaped_filter_value_x( &vals[ i ], &fvals[ i ],
			1, op->o_tmpmemctx );
		op2.ors_filterstr.bv_len += ad_rdnValue->ad_cname.bv_len
			+ fvals[ i ].bv_len + STRLENOF( "(=)" );
	}

	op2.ors_filterstr.bv_val = op->o_tmpalloc( op2.ors_filterstr.bv_len + 1, op->o_tmpmemctx );

	ptr = op2.ors_filterstr.bv_val;
	if ( i > 1 ) {
		ptr = lutil_strcopy( ptr, "(&" );
	}
	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
		*ptr++ = '(';
		ptr = lutil_strncopy( ptr, ad_rdnValue->ad_cname.bv_val, ad_rdnValue->ad_cname.bv_len );
		*ptr++ = '=';
		ptr = lutil_strncopy( ptr, fvals[ i ].bv_val, fvals[ i ].bv_len );
		*ptr++ = ')';
	}

	if ( i > 1 ) {
		*ptr++ = ')';
	}
	*ptr = '\0';

	assert( ptr == op2.ors_filterstr.bv_val + op2.ors_filterstr.bv_len );
	op2.ors_filter = str2filter_x( op, op2.ors_filterstr.bv_val );
	assert( op2.ors_filter != NULL );

	(void)op2.o_bd->be_search( &op2, &rs2 );

	filter_free_x( op, op2.ors_filter, 1 );
	op->o_tmpfree( op2.ors_filterstr.bv_val, op->o_tmpmemctx );
	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
		if ( vals[ i ].bv_val != fvals[ i ].bv_val ) {
			op->o_tmpfree( fvals[ i ].bv_val, op->o_tmpmemctx );
		}
	}
	op->o_tmpfree( fvals, op->o_tmpmemctx );

	if ( rs2.sr_err != LDAP_SUCCESS || gotit > 0 ) {
		return LDAP_CONSTRAINT_VIOLATION;
	}

	return LDAP_SUCCESS;
}
Exemplo n.º 13
0
/*
 * call from within ldap_back_db_open()
 */
int
ldap_back_monitor_db_open( BackendDB *be )
{
	ldapinfo_t		*li = (ldapinfo_t *) be->be_private;
	char			buf[ BACKMONITOR_BUFSIZE ];
	Entry			*e = NULL;
	monitor_callback_t	*cb = NULL;
	struct berval		suffix, *filter, *base;
	char			*ptr;
	time_t			now;
	char			timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
	struct berval 		timestamp;
	int			rc = 0;
	BackendInfo		*mi;
	monitor_extra_t		*mbe;

	if ( !SLAP_DBMONITORING( be ) ) {
		return 0;
	}

	/* check if monitor is configured and usable */
	mi = backend_info( "monitor" );
	if ( !mi || !mi->bi_extra ) {
		SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
		return 0;
 	}
 	mbe = mi->bi_extra;

	/* don't bother if monitor is not configured */
	if ( !mbe->is_configured() ) {
		static int warning = 0;

		if ( warning++ == 0 ) {
			Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: "
				"monitoring disabled; "
				"configure monitor database to enable\n",
				0, 0, 0 );
		}

		return 0;
	}

	/* set up the fake subsystem that is used to create
	 * the volatile connection entries */
	li->li_monitor_info.lmi_mss.mss_name = "back-ldap";
	li->li_monitor_info.lmi_mss.mss_flags = MONITOR_F_VOLATILE_CH;
	li->li_monitor_info.lmi_mss.mss_create = ldap_back_monitor_conn_create;

	li->li_monitor_info.lmi_li = li;
	li->li_monitor_info.lmi_scope = LDAP_SCOPE_SUBORDINATE;
	base = &li->li_monitor_info.lmi_base;
	BER_BVSTR( base, "cn=databases,cn=monitor" );
	filter = &li->li_monitor_info.lmi_filter;
	BER_BVZERO( filter );

	suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
	if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
		suffix = be->be_nsuffix[ 0 ];

	} else {
		ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
	}
	
	filter->bv_len = STRLENOF( "(&" )
		+ li->li_monitor_info.lmi_more_filter.bv_len
		+ STRLENOF( "(monitoredInfo=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( ")(!(monitorOverlay=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( "))(namingContexts:distinguishedNameMatch:=" )
		+ suffix.bv_len + STRLENOF( "))" );
	ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
	ptr = lutil_strcopy( ptr, "(&" );
	ptr = lutil_strncopy( ptr, li->li_monitor_info.lmi_more_filter.bv_val,
		li->li_monitor_info.lmi_more_filter.bv_len );
	ptr = lutil_strcopy( ptr, "(monitoredInfo=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, ")(!(monitorOverlay=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, "))(namingContexts:distinguishedNameMatch:=" );
	ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
	ptr = lutil_strcopy( ptr, "))" );
	ptr[ 0 ] = '\0';
	assert( ptr == &filter->bv_val[ filter->bv_len ] );

	if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
		ch_free( suffix.bv_val );
	}

	now = slap_get_time();
	timestamp.bv_val = timebuf;
	timestamp.bv_len = sizeof( timebuf );
	slap_timestamp( &now, &timestamp );

	/* caller (e.g. an overlay based on back-ldap) may want to use
	 * a different RDN... */
	if ( BER_BVISNULL( &li->li_monitor_info.lmi_rdn ) ) {
		ber_str2bv( "cn=Connections", 0, 1, &li->li_monitor_info.lmi_rdn );
	}

	ptr = ber_bvchr( &li->li_monitor_info.lmi_rdn, '=' );
	assert( ptr != NULL );
	ptr[ 0 ] = '\0';
	ptr++;

	snprintf( buf, sizeof( buf ),
		"dn: %s=%s\n"
		"objectClass: monitorContainer\n"
		"%s: %s\n"
		"creatorsName: %s\n"
		"createTimestamp: %s\n"
		"modifiersName: %s\n"
		"modifyTimestamp: %s\n",
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val );
	e = str2entry( buf );
	if ( e == NULL ) {
		rc = -1;
		goto cleanup;
	}

	ptr[ -1 ] = '=';

	/* add labeledURI and special, modifiable URI value */
	if ( li->li_uri != NULL ) {
		struct berval	bv;
		LDAPURLDesc	*ludlist = NULL;
		int		rc;

		rc = ldap_url_parselist_ext( &ludlist,
			li->li_uri, NULL,
			LDAP_PVT_URL_PARSE_NOEMPTY_HOST
				| LDAP_PVT_URL_PARSE_DEF_PORT );
		if ( rc != LDAP_URL_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
				"ldap_back_monitor_db_open: "
				"unable to parse URI list (ignored)\n",
				0, 0, 0 );
		} else {
			for ( ; ludlist != NULL; ) {
				LDAPURLDesc	*next = ludlist->lud_next;

				bv.bv_val = ldap_url_desc2str( ludlist );
				assert( bv.bv_val != NULL );
				ldap_free_urldesc( ludlist );
				bv.bv_len = strlen( bv.bv_val );
				attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI,
					&bv, NULL );
				ch_free( bv.bv_val );

				ludlist = next;
			}
		}
		
		ber_str2bv( li->li_uri, 0, 0, &bv );
		attr_merge_normalize_one( e, ad_olmDbURIList,
			&bv, NULL );
	}

	ber_dupbv( &li->li_monitor_info.lmi_nrdn, &e->e_nname );

	cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
	cb->mc_update = ldap_back_monitor_update;
	cb->mc_modify = ldap_back_monitor_modify;
	cb->mc_free = ldap_back_monitor_free;
	cb->mc_private = (void *)li;

	rc = mbe->register_entry_parent( e, cb,
		(monitor_subsys_t *)&li->li_monitor_info,
		MONITOR_F_VOLATILE_CH,
		base, LDAP_SCOPE_SUBORDINATE, filter );

cleanup:;
	if ( rc != 0 ) {
		if ( cb != NULL ) {
			ch_free( cb );
			cb = NULL;
		}

		if ( e != NULL ) {
			entry_free( e );
			e = NULL;
		}

		if ( !BER_BVISNULL( filter ) ) {
			ch_free( filter->bv_val );
			BER_BVZERO( filter );
		}
	}

	/* store for cleanup */
	li->li_monitor_info.lmi_cb = (void *)cb;

	if ( e != NULL ) {
		entry_free( e );
	}

	return rc;
}
Exemplo n.º 14
0
/*
 * call from within bdb_db_open()
 */
int
bdb_monitor_db_open( BackendDB *be )
{
	struct bdb_info		*bdb = (struct bdb_info *) be->be_private;
	Attribute		*a, *next;
	monitor_callback_t	*cb = NULL;
	int			rc = 0;
	BackendInfo		*mi;
	monitor_extra_t		*mbe;
	struct berval dummy = BER_BVC("");

	if ( !SLAP_DBMONITORING( be ) ) {
		return 0;
	}

	mi = backend_info( "monitor" );
	if ( !mi || !mi->bi_extra ) {
		SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
		return 0;
	}
	mbe = mi->bi_extra;

	/* don't bother if monitor is not configured */
	if ( !mbe->is_configured() ) {
		static int warning = 0;

		if ( warning++ == 0 ) {
			Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_db_open)
				": monitoring disabled; "
				"configure monitor database to enable\n",
				0, 0, 0 );
		}

		return 0;
	}

	/* alloc as many as required (plus 1 for objectClass) */
	a = attrs_alloc( 1 + 4 );
	if ( a == NULL ) {
		rc = 1;
		goto cleanup;
	}

	a->a_desc = slap_schema.si_ad_objectClass;
	attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 );
	next = a->a_next;

	{
		struct berval	bv = BER_BVC( "0" );

		next->a_desc = ad_olmBDBEntryCache;
		attr_valadd( next, &bv, NULL, 1 );
		next = next->a_next;

		next->a_desc = ad_olmBDBDNCache;
		attr_valadd( next, &bv, NULL, 1 );
		next = next->a_next;

		next->a_desc = ad_olmBDBIDLCache;
		attr_valadd( next, &bv, NULL, 1 );
		next = next->a_next;
	}

	{
		struct berval	bv, nbv;
		ber_len_t	pathlen = 0, len = 0;
		char		path[ MAXPATHLEN ] = { '\0' };
		char		*fname = bdb->bi_dbenv_home,
				*ptr;

		len = strlen( fname );
		if ( fname[ 0 ] != '/' ) {
			/* get full path name */
			getcwd( path, sizeof( path ) );
			pathlen = strlen( path );

			if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) {
				fname += 2;
				len -= 2;
			}
		}

		bv.bv_len = pathlen + STRLENOF( "/" ) + len;
		ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 );
		if ( pathlen ) {
			ptr = lutil_strncopy( ptr, path, pathlen );
			ptr[ 0 ] = '/';
			ptr++;
		}
		ptr = lutil_strncopy( ptr, fname, len );
		if ( ptr[ -1 ] != '/' ) {
			ptr[ 0 ] = '/';
			ptr++;
		}
		ptr[ 0 ] = '\0';
		
		attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL );

		next->a_desc = ad_olmDbDirectory;
		next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
		next->a_vals[ 0 ] = bv;
		next->a_numvals = 1;

		if ( BER_BVISNULL( &nbv ) ) {
			next->a_nvals = next->a_vals;

		} else {
			next->a_nvals = ch_calloc( sizeof( struct berval ), 2 );
			next->a_nvals[ 0 ] = nbv;
		}

		next = next->a_next;
	}

	cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
	cb->mc_update = bdb_monitor_update;
#if 0	/* uncomment if required */
	cb->mc_modify = bdb_monitor_modify;
#endif
	cb->mc_free = bdb_monitor_free;
	cb->mc_private = (void *)bdb;

	/* make sure the database is registered; then add monitor attributes */
	rc = mbe->register_database( be, &bdb->bi_monitor.bdm_ndn );
	if ( rc == 0 ) {
		rc = mbe->register_entry_attrs( &bdb->bi_monitor.bdm_ndn, a, cb,
			&dummy, 0, &dummy );
	}

cleanup:;
	if ( rc != 0 ) {
		if ( cb != NULL ) {
			ch_free( cb );
			cb = NULL;
		}

		if ( a != NULL ) {
			attrs_free( a );
			a = NULL;
		}
	}

	/* store for cleanup */
	bdb->bi_monitor.bdm_cb = (void *)cb;

	/* we don't need to keep track of the attributes, because
	 * bdb_monitor_free() takes care of everything */
	if ( a != NULL ) {
		attrs_free( a );
	}

	return rc;
}
Exemplo n.º 15
0
/* We add two elements to the DN2ID database - a data item under the parent's
 * entryID containing the child's RDN and entryID, and an item under the
 * child's entryID containing the parent's entryID.
 */
int
mdb_dn2id_add(
	Operation	*op,
	MDB_cursor	*mcp,
	MDB_cursor	*mcd,
	ID pid,
	ID nsubs,
	int upsub,
	Entry		*e )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_val		key, data;
	ID		nid;
	int		rc, rlen, nrlen;
	diskNode *d;
	char *ptr;

	Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2id_add 0x%lx: \"%s\"\n",
		e->e_id, e->e_ndn ? e->e_ndn : "" );

	nrlen = dn_rdnlen( op->o_bd, &e->e_nname );
	if (nrlen) {
		rlen = dn_rdnlen( op->o_bd, &e->e_name );
	} else {
		nrlen = e->e_nname.bv_len;
		rlen = e->e_name.bv_len;
	}

	d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen + sizeof(ID), op->o_tmpmemctx);
	d->nrdnlen[1] = nrlen & 0xff;
	d->nrdnlen[0] = (nrlen >> 8) | 0x80;
	ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );
	*ptr++ = '\0';
	ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );
	*ptr++ = '\0';
	memcpy( ptr, &e->e_id, sizeof( ID ));
	ptr += sizeof( ID );
	memcpy( ptr, &nsubs, sizeof( ID ));

	key.mv_size = sizeof(ID);
	key.mv_data = &nid;

	nid = pid;

	/* Need to make dummy root node once. Subsequent attempts
	 * will fail harmlessly.
	 */
	if ( pid == 0 ) {
		diskNode dummy = {{0, 0}, "", "", ""};
		data.mv_data = &dummy;
		data.mv_size = sizeof(diskNode);

		mdb_cursor_put( mcp, &key, &data, MDB_NODUPDATA );
	}

	data.mv_data = d;
	data.mv_size = sizeof(diskNode) + rlen + nrlen + sizeof( ID );

	/* Add our child node under parent's key */
	rc = mdb_cursor_put( mcp, &key, &data, MDB_NODUPDATA );

	/* Add our own node */
	if (rc == 0) {
		int flag = MDB_NODUPDATA;
		nid = e->e_id;
		/* drop subtree count */
		data.mv_size -= sizeof( ID );
		ptr -= sizeof( ID );
		memcpy( ptr, &pid, sizeof( ID ));
		d->nrdnlen[0] ^= 0x80;

		if ((slapMode & SLAP_TOOL_MODE) || (e->e_id == mdb_read_nextid(mdb)))
			flag |= MDB_APPEND;
		rc = mdb_cursor_put( mcd, &key, &data, flag );
	}
	op->o_tmpfree( d, op->o_tmpmemctx );

	/* Add our subtree count to all superiors */
	if ( rc == 0 && upsub && pid ) {
		ID subs;
		nid = pid;
		do {
			/* Get parent's RDN */
			rc = mdb_cursor_get( mcp, &key, &data, MDB_SET );
			if ( !rc ) {
				char *p2;
				ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
				memcpy( &nid, ptr, sizeof( ID ));
				/* Get parent's node under grandparent */
				d = data.mv_data;
				rlen = ( d->nrdnlen[0] << 8 ) | d->nrdnlen[1];
				p2 = op->o_tmpalloc( rlen + 2, op->o_tmpmemctx );
				memcpy( p2, data.mv_data, rlen+2 );
				*p2 ^= 0x80;
				data.mv_data = p2;
				rc = mdb_cursor_get( mcp, &key, &data, MDB_GET_BOTH );
				op->o_tmpfree( p2, op->o_tmpmemctx );
				if ( !rc ) {
					/* Get parent's subtree count */
					ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
					memcpy( &subs, ptr, sizeof( ID ));
					subs += nsubs;
					p2 = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
					memcpy( p2, data.mv_data, data.mv_size - sizeof( ID ));
					memcpy( p2+data.mv_size - sizeof( ID ), &subs, sizeof( ID ));
					data.mv_data = p2;
					rc = mdb_cursor_put( mcp, &key, &data, MDB_CURRENT );
					op->o_tmpfree( p2, op->o_tmpmemctx );
				}
			}
			if ( rc )
				break;
		} while ( nid );
	}

	Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id_add 0x%lx: %d\n", e->e_id, rc );

	return rc;
}
Exemplo n.º 16
0
/* return IDs from root to parent of DN */
int
mdb_dn2sups(
	Operation	*op,
	MDB_txn *txn,
	struct berval	*in,
	ID	*ids )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_cursor *cursor;
	MDB_dbi dbi = mdb->mi_dn2id;
	MDB_val		key, data;
	int		rc = 0, nrlen;
	diskNode *d;
	char	*ptr;
	ID pid, nid;
	struct berval tmp;

	Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2sups(\"%s\")\n", in->bv_val );

	if ( !in->bv_len ) {
		goto done;
	}

	tmp = *in;

	nrlen = tmp.bv_len - op->o_bd->be_nsuffix[0].bv_len;
	tmp.bv_val += nrlen;
	tmp.bv_len = op->o_bd->be_nsuffix[0].bv_len;
	nid = 0;
	key.mv_size = sizeof(ID);

	rc = mdb_cursor_open( txn, dbi, &cursor );
	if ( rc ) goto done;

	for (;;) {
		key.mv_data = &pid;
		pid = nid;

		data.mv_size = sizeof(diskNode) + tmp.bv_len;
		d = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
		d->nrdnlen[1] = tmp.bv_len & 0xff;
		d->nrdnlen[0] = (tmp.bv_len >> 8) | 0x80;
		ptr = lutil_strncopy( d->nrdn, tmp.bv_val, tmp.bv_len );
		*ptr = '\0';
		data.mv_data = d;
		rc = mdb_cursor_get( cursor, &key, &data, MDB_GET_BOTH );
		op->o_tmpfree( d, op->o_tmpmemctx );
		if ( rc ) {
			mdb_cursor_close( cursor );
			break;
		}
		ptr = (char *) data.mv_data + data.mv_size - 2*sizeof(ID);
		memcpy( &nid, ptr, sizeof(ID));

		if ( pid )
			mdb_idl_insert( ids, pid );

		if ( tmp.bv_val > in->bv_val ) {
			for (ptr = tmp.bv_val - 2; ptr > in->bv_val &&
				!DN_SEPARATOR(*ptr); ptr--)	/* empty */;
			if ( ptr >= in->bv_val ) {
				if (DN_SEPARATOR(*ptr)) ptr++;
				tmp.bv_len = tmp.bv_val - ptr - 1;
				tmp.bv_val = ptr;
			}
		} else {
			break;
		}
	}

done:
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2sups: get failed: %s (%d)\n",
			mdb_strerror( rc ), rc );
	}

	return rc;
}
Exemplo n.º 17
0
static int
pguid_repair_cb( Operation *op, SlapReply *rs )
{
	int rc;
	pguid_repair_cb_t *pcb = op->o_callback->sc_private;
	Entry *e = NULL;
	Attribute *a;
	struct berval pdn, pndn;

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

	case REP_SEARCHREF:
	case REP_RESULT:
		return rs->sr_err;

	default:
		assert( 0 );
	}

	assert( rs->sr_entry != NULL );

	dnParent( &rs->sr_entry->e_name, &pdn );
	dnParent( &rs->sr_entry->e_nname, &pndn );

	rc = overlay_entry_get_ov( op, &pndn, NULL, slap_schema.si_ad_entryUUID, 0, &e, pcb->on );
	if ( rc != LDAP_SUCCESS || e == NULL ) {
		Debug( LDAP_DEBUG_ANY, "%s: pguid_repair_cb: unable to get parent entry DN=\"%s\" (%d)\n",
			op->o_log_prefix, pdn.bv_val, rc );
		return 0;
	}

	a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
	if ( a == NULL ) {
		Debug( LDAP_DEBUG_ANY, "%s: pguid_repair_cb: unable to find entryUUID of parent entry DN=\"%s\" (%d)\n",
			op->o_log_prefix, pdn.bv_val, rc );
		
	} else {
		ber_len_t len;
		pguid_mod_t *mod;

		assert( a->a_numvals == 1 );

		len = sizeof( pguid_mod_t ) + rs->sr_entry->e_nname.bv_len + 1 + a->a_vals[0].bv_len + 1;
		mod = op->o_tmpalloc( len, op->o_tmpmemctx );
		mod->ndn.bv_len = rs->sr_entry->e_nname.bv_len;
		mod->ndn.bv_val = (char *)&mod[1];
		mod->pguid.bv_len = a->a_vals[0].bv_len;
		mod->pguid.bv_val = (char *)&mod->ndn.bv_val[mod->ndn.bv_len + 1];
		lutil_strncopy( mod->ndn.bv_val, rs->sr_entry->e_nname.bv_val, rs->sr_entry->e_nname.bv_len );
		lutil_strncopy( mod->pguid.bv_val, a->a_vals[0].bv_val, a->a_vals[0].bv_len );

		mod->next = pcb->mods;
		pcb->mods = mod;

		Debug( LDAP_DEBUG_TRACE, "%s: pguid_repair_cb: scheduling entry DN=\"%s\" for repair\n",
			op->o_log_prefix, rs->sr_entry->e_name.bv_val, 0 );
	}

	if ( e != NULL ) {
		(void)overlay_entry_release_ov( op, e, 0, pcb->on );
	}

	return 0;
}
Exemplo n.º 18
0
static int
OpenLDAPaciNormalizeRight(
	struct berval	*action,
	struct berval	*naction,
	void		*ctx )
{
	struct berval	grantdeny,
			perms = BER_BVNULL,
			bv = BER_BVNULL;
	int		idx,
			i;

	/* grant|deny */
	if ( acl_get_part( action, 0, ';', &grantdeny ) < 0 ) {
	        Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: missing ';' in '%s'\n", action->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	idx = bv_getcaseidx( &grantdeny, ACIgrantdeny );
	if ( idx == -1 ) {
	        Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: '%s' must be grant or deny\n", grantdeny.bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	ber_dupbv_x( naction, (struct berval *)ACIgrantdeny[ idx ], ctx );

	for ( i = 1; acl_get_part( action, i, ';', &bv ) >= 0; i++ ) {
		struct berval	nattrs = BER_BVNULL;
		int		freenattrs = 1;
		if ( i & 1 ) {
			/* perms */
			if ( OpenLDAPaciValidatePerms( &bv ) != LDAP_SUCCESS )
			{
				return LDAP_INVALID_SYNTAX;
			}
			perms = bv;

		} else {
			/* attr */
			char		*ptr;

			/* could be "[all]" or an attribute description */
			if ( ber_bvstrcasecmp( &bv, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) {
				nattrs = aci_bv[ ACI_BV_BR_ALL ];
				freenattrs = 0;

			} else {
				AttributeDescription	*ad = NULL;
				AttributeDescription	adstatic= { 0 };
				const char		*text = NULL;
				struct berval		attr, left, right;
				int			j;
				int			len;

				for ( j = 0; acl_get_part( &bv, j, ',', &attr ) >= 0; j++ )
				{
					ad = NULL;
					text = NULL;
					/* openldap 2.1 aci compabitibility [entry] -> entry */
					if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ENTRY ] ) == 0 ) {
						ad = &adstatic;
						adstatic.ad_cname = aci_bv[ ACI_BV_ENTRY ];

					/* openldap 2.1 aci compabitibility [children] -> children */
					} else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_CHILDREN ] ) == 0 ) {
						ad = &adstatic;
						adstatic.ad_cname = aci_bv[ ACI_BV_CHILDREN ];

					/* openldap 2.1 aci compabitibility [all] -> only [all] */
					} else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) {
						ber_memfree_x( nattrs.bv_val, ctx );
						nattrs = aci_bv[ ACI_BV_BR_ALL ];
						freenattrs = 0;
						break;

					} else if ( acl_get_part( &attr, 0, '=', &left ) < 0
				     		|| acl_get_part( &attr, 1, '=', &right ) < 0 )
					{
						if ( slap_bv2ad( &attr, &ad, &text ) != LDAP_SUCCESS )
						{
							ber_memfree_x( nattrs.bv_val, ctx );
							Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", attr.bv_val );
							return LDAP_INVALID_SYNTAX;
						}

					} else {
						if ( slap_bv2ad( &left, &ad, &text ) != LDAP_SUCCESS )
						{
							ber_memfree_x( nattrs.bv_val, ctx );
							Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", left.bv_val );
							return LDAP_INVALID_SYNTAX;
						}
					}


					len = nattrs.bv_len + ( !BER_BVISEMPTY( &nattrs ) ? STRLENOF( "," ) : 0 )
				      		+ ad->ad_cname.bv_len;
					nattrs.bv_val = ber_memrealloc_x( nattrs.bv_val, len + 1, ctx );
	                        	ptr = &nattrs.bv_val[ nattrs.bv_len ];
					if ( !BER_BVISEMPTY( &nattrs ) ) {
						*ptr++ = ',';
					}
					ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len );
                                	ptr[ 0 ] = '\0';
                                	nattrs.bv_len = len;
				}

			}

			naction->bv_val = ber_memrealloc_x( naction->bv_val,
				naction->bv_len + STRLENOF( ";" )
				+ perms.bv_len + STRLENOF( ";" )
				+ nattrs.bv_len + 1,
				ctx );

			ptr = &naction->bv_val[ naction->bv_len ];
			ptr[ 0 ] = ';';
			ptr++;
			ptr = lutil_strncopy( ptr, perms.bv_val, perms.bv_len );
			ptr[ 0 ] = ';';
			ptr++;
			ptr = lutil_strncopy( ptr, nattrs.bv_val, nattrs.bv_len );
			ptr[ 0 ] = '\0';
			naction->bv_len += STRLENOF( ";" ) + perms.bv_len
				+ STRLENOF( ";" ) + nattrs.bv_len;
			if ( freenattrs ) {
				ber_memfree_x( nattrs.bv_val, ctx );
			}
		}
	}

	/* perms;attr go in pairs */
	if ( i > 1 && ( i & 1 ) ) {
		return LDAP_SUCCESS;

	} else {
		Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: perms:attr need to be pairs in '%s'\n", action->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
}
Exemplo n.º 19
0
int
hdb_dn2id(
	Operation	*op,
	struct berval	*in,
	EntryInfo	*ei,
	DB_TXN *txn,
	DBC **cursor )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	DB *db = bdb->bi_dn2id->bdi_db;
	DBT		key, data;
	int		rc = 0, nrlen;
	diskNode *d;
	char	*ptr;
	unsigned char dlen[2];
	ID idp, parentID;

	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id(\"%s\")\n", in->bv_val, 0, 0 );

	nrlen = dn_rdnlen( op->o_bd, in );
	if (!nrlen) nrlen = in->bv_len;

	DBTzero(&key);
	key.size = sizeof(ID);
	key.data = &idp;
	key.ulen = sizeof(ID);
	key.flags = DB_DBT_USERMEM;
	parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0;
	BDB_ID2DISK( parentID, &idp );

	DBTzero(&data);
	data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1;
	data.ulen = data.size * 3;
	data.dlen = data.ulen;
	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;

	rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );
	if ( rc ) return rc;

	d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
	d->nrdnlen[1] = nrlen & 0xff;
	d->nrdnlen[0] = (nrlen >> 8) | 0x80;
	dlen[0] = d->nrdnlen[0];
	dlen[1] = d->nrdnlen[1];
	ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
	*ptr = '\0';
	data.data = d;

	rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE );
	if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] ||
		strncmp( d->nrdn, in->bv_val, nrlen ))) {
		rc = DB_NOTFOUND;
	}
	if ( rc == 0 ) {
		ptr = (char *) data.data + data.size - sizeof(ID);
		BDB_DISK2ID( ptr, &ei->bei_id );
		ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
		ptr = d->nrdn + nrlen + 1;
		ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
		if ( ei->bei_parent != NULL && !ei->bei_parent->bei_dkids ) {
			db_recno_t dkids;
			/* How many children does the parent have? */
			/* FIXME: do we need to lock the parent
			 * entryinfo? Seems safe...
			 */
			(*cursor)->c_count( *cursor, &dkids, 0 );
			ei->bei_parent->bei_dkids = dkids;
		}
	}

	op->o_tmpfree( d, op->o_tmpmemctx );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: get failed: %s (%d)\n",
			db_strerror( rc ), rc, 0 );
	} else {
		Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: got id=0x%lx\n",
			ei->bei_id, 0, 0 );
	}

	return rc;
}
Exemplo n.º 20
0
static int
collect_cf( ConfigArgs *c )
{
	slap_overinst *on = (slap_overinst *)c->bi;
	int rc = 1, idx;

	switch( c->op ) {
	case SLAP_CONFIG_EMIT:
		{
		collect_info *ci;
		for ( ci = on->on_bi.bi_private; ci; ci = ci->ci_next ) {
			struct berval bv;
			char *ptr;
			int len;

			/* calculate the length & malloc memory */
			bv.bv_len = ci->ci_dn.bv_len + STRLENOF("\"\" ");
			for (idx=0; idx<ci->ci_ad_num; idx++) {
				bv.bv_len += ci->ci_ad[idx]->ad_cname.bv_len;
				if (idx<(ci->ci_ad_num-1)) { 
					bv.bv_len++;
				}
			}
			bv.bv_val = ch_malloc( bv.bv_len + 1 );

			/* copy the value and update len */
			len = snprintf( bv.bv_val, bv.bv_len + 1, "\"%s\" ", 
				ci->ci_dn.bv_val);
			ptr = bv.bv_val + len;
			for (idx=0; idx<ci->ci_ad_num; idx++) {
				ptr = lutil_strncopy( ptr,
					ci->ci_ad[idx]->ad_cname.bv_val,
					ci->ci_ad[idx]->ad_cname.bv_len);
				if (idx<(ci->ci_ad_num-1)) {
					*ptr++ = ',';
				}
			}
			*ptr = '\0';
			bv.bv_len = ptr - bv.bv_val;

			ber_bvarray_add( &c->rvalue_vals, &bv );
			rc = 0;
		}
		}
		break;
	case LDAP_MOD_DELETE:
		if ( c->valx == -1 ) {
		/* Delete entire attribute */
			collect_info *ci;
			while (( ci = on->on_bi.bi_private )) {
				on->on_bi.bi_private = ci->ci_next;
				ch_free( ci->ci_dn.bv_val );
				ch_free( ci );
			}
		} else {
		/* Delete just one value */
			collect_info **cip, *ci;
			int i;
			cip = (collect_info **)&on->on_bi.bi_private;
			ci = *cip;
			for ( i=0; i < c->valx; i++ ) {
				cip = &ci->ci_next;
				ci = *cip;
			}
			*cip = ci->ci_next;
			ch_free( ci->ci_dn.bv_val );
			ch_free( ci );
		}
		rc = 0;
		break;
	case SLAP_CONFIG_ADD:
	case LDAP_MOD_ADD:
		{
		collect_info *ci;
		struct berval bv, dn;
		const char *text;
		int idx, count=0;
		char *arg;

		/* count delimiters in attribute argument */
		arg = strtok(c->argv[2], ",");
		while (arg!=NULL) {
			count++;
			arg = strtok(NULL, ",");
		}

		/* validate and normalize dn */
		ber_str2bv( c->argv[1], 0, 0, &bv );
		if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid DN: \"%s\"",
				c->argv[0], c->argv[1] );
			Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
				"%s: %s\n", c->log, c->cr_msg, 0 );
			return ARG_BAD_CONF;
		}

		/* check for duplicate DNs */
		for ( ci = (collect_info *)on->on_bi.bi_private; ci;
			ci = ci->ci_next ) {
			/* If new DN is longest, there are no possible matches */
			if ( dn.bv_len > ci->ci_dn.bv_len ) {
				ci = NULL;
				break;
			}
			if ( bvmatch( &dn, &ci->ci_dn )) {
				break;
			}
		}
		if ( ci ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s DN already configured: \"%s\"",
				c->argv[0], c->argv[1] );
			Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
				"%s: %s\n", c->log, c->cr_msg, 0 );
			return ARG_BAD_CONF;
		}

		/* allocate config info with room for attribute array */
		ci = ch_malloc( sizeof( collect_info ) +
			sizeof( AttributeDescription * ) * count );

		/* load attribute description for attribute list */
		arg = c->argv[2];
		for( idx=0; idx<count; idx++) {
			ci->ci_ad[idx] = NULL;

			if ( slap_str2ad( arg, &ci->ci_ad[idx], &text ) ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), 
					"%s attribute description unknown: \"%s\"",
					c->argv[0], arg);
				Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
					"%s: %s\n", c->log, c->cr_msg, 0 );
				ch_free( ci );
				return ARG_BAD_CONF;
			}
			while(*arg!='\0') {
				arg++; /* skip to end of argument */
			}
			if (idx<count-1) {
				arg++; /* skip inner delimiters */
			}
		}

		/* The on->on_bi.bi_private pointer can be used for
		 * anything this instance of the overlay needs.
		 */
		ci->ci_ad[count] = NULL;
		ci->ci_ad_num = count;
		ci->ci_dn = dn;

		/* creates list of ci's ordered by dn length */ 
		insert_ordered ( on, ci );

		/* New ci wasn't simply appended to end, adjust its
		 * position in the config entry's a_vals
		 */
		if ( c->ca_entry && ci->ci_next ) {
			Attribute *a = attr_find( c->ca_entry->e_attrs,
				collectcfg[0].ad );
			if ( a ) {
				struct berval bv, nbv;
				collect_info *c2 = (collect_info *)on->on_bi.bi_private;
				int i, j;
				for ( i=0; c2 != ci; i++, c2 = c2->ci_next );
				bv = a->a_vals[a->a_numvals-1];
				nbv = a->a_nvals[a->a_numvals-1];
				for ( j=a->a_numvals-1; j>i; j-- ) {
					a->a_vals[j] = a->a_vals[j-1];
					a->a_nvals[j] = a->a_nvals[j-1];
				}
				a->a_vals[j] = bv;
				a->a_nvals[j] = nbv;
			}
		}

		rc = 0;
		}
	}
	return rc;
}
Exemplo n.º 21
0
int slap_bv2ad(
	struct berval *bv,
	AttributeDescription **ad,
	const char **text )
{
	int rtn = LDAP_UNDEFINED_TYPE;
	AttributeDescription desc, *d2;
	char *name, *options, *optn;
	char *opt, *next;
	int ntags;
	int tagslen;

	/* hardcoded limits for speed */
#define MAX_TAGGING_OPTIONS 128
	struct berval tags[MAX_TAGGING_OPTIONS+1];
#define MAX_TAGS_LEN 1024
	char tagbuf[MAX_TAGS_LEN];

	assert( ad != NULL );
	assert( *ad == NULL ); /* temporary */

	if( bv == NULL || BER_BVISNULL( bv ) || BER_BVISEMPTY( bv ) ) {
		*text = "empty AttributeDescription";
		return rtn;
	}

	/* make sure description is IA5 */
	if( ad_keystring( bv ) ) {
		*text = "AttributeDescription contains inappropriate characters";
		return rtn;
	}

	/* find valid base attribute type; parse in place */
	desc.ad_cname = *bv;
	desc.ad_flags = 0;
	BER_BVZERO( &desc.ad_tags );
	name = bv->bv_val;
	options = ber_bvchr( bv, ';' );
	if ( options != NULL && (unsigned) ( options - name ) < bv->bv_len ) {
		/* don't go past the end of the berval! */
		desc.ad_cname.bv_len = options - name;
	} else {
		options = NULL;
	}
	desc.ad_type = at_bvfind( &desc.ad_cname );
	if( desc.ad_type == NULL ) {
		*text = "attribute type undefined";
		return rtn;
	}

	if( is_at_operational( desc.ad_type ) && options != NULL ) {
		*text = "operational attribute with options undefined";
		return rtn;
	}

	/*
	 * parse options in place
	 */
	ntags = 0;
	tagslen = 0;
	optn = bv->bv_val + bv->bv_len;

	for( opt=options; opt != NULL; opt=next ) {
		int optlen;
		opt++; 
		next = strchrlen( opt, optn, ';', &optlen );

		if( optlen == 0 ) {
			*text = "zero length option is invalid";
			return rtn;
		
		} else if ( optlen == STRLENOF("binary") &&
			strncasecmp( opt, "binary", STRLENOF("binary") ) == 0 )
		{
			/* binary option */
			if( slap_ad_is_binary( &desc ) ) {
				*text = "option \"binary\" specified multiple times";
				return rtn;
			}

			if( !slap_syntax_is_binary( desc.ad_type->sat_syntax )) {
				/* not stored in binary, disallow option */
				*text = "option \"binary\" not supported with type";
				return rtn;
			}

			desc.ad_flags |= SLAP_DESC_BINARY;
			continue;

		} else if ( ad_find_option_definition( opt, optlen ) ) {
			int i;

			if( opt[optlen-1] == '-' ||
				( opt[optlen-1] == '=' && msad_range_hack )) {
				desc.ad_flags |= SLAP_DESC_TAG_RANGE;
			}

			if( ntags >= MAX_TAGGING_OPTIONS ) {
				*text = "too many tagging options";
				return rtn;
			}

			/*
			 * tags should be presented in sorted order,
			 * so run the array in reverse.
			 */
			for( i=ntags-1; i>=0; i-- ) {
				int rc;

				rc = strncasecmp( opt, tags[i].bv_val,
					(unsigned) optlen < tags[i].bv_len
						? (unsigned) optlen : tags[i].bv_len );

				if( rc == 0 && (unsigned)optlen == tags[i].bv_len ) {
					/* duplicate (ignore) */
					ntags--;
					goto done;

				} else if ( rc > 0 ||
					( rc == 0 && (unsigned)optlen > tags[i].bv_len ))
				{
					AC_MEMCPY( &tags[i+2], &tags[i+1],
						(ntags-i-1)*sizeof(struct berval) );
					tags[i+1].bv_val = opt;
					tags[i+1].bv_len = optlen;
					goto done;
				}
			}

			if( ntags ) {
				AC_MEMCPY( &tags[1], &tags[0],
					ntags*sizeof(struct berval) );
			}
			tags[0].bv_val = opt;
			tags[0].bv_len = optlen;

done:;
			tagslen += optlen + 1;
			ntags++;

		} else {
			*text = "unrecognized option";
			return rtn;
		}
	}

	if( ntags > 0 ) {
		int i;

		if( tagslen > MAX_TAGS_LEN ) {
			*text = "tagging options too long";
			return rtn;
		}

		desc.ad_tags.bv_val = tagbuf;
		tagslen = 0;

		for( i=0; i<ntags; i++ ) {
			AC_MEMCPY( &desc.ad_tags.bv_val[tagslen],
				tags[i].bv_val, tags[i].bv_len );

			tagslen += tags[i].bv_len;
			desc.ad_tags.bv_val[tagslen++] = ';';
		}

		desc.ad_tags.bv_val[--tagslen] = '\0';
		desc.ad_tags.bv_len = tagslen;
	}

	/* see if a matching description is already cached */
	for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) {
		if( d2->ad_flags != desc.ad_flags ) {
			continue;
		}
		if( d2->ad_tags.bv_len != desc.ad_tags.bv_len ) {
			continue;
		}
		if( d2->ad_tags.bv_len == 0 ) {
			break;
		}
		if( strncasecmp( d2->ad_tags.bv_val, desc.ad_tags.bv_val,
			desc.ad_tags.bv_len ) == 0 )
		{
			break;
		}
	}

	/* Not found, add new one */
	while (d2 == NULL) {
		size_t dlen = 0;
		ldap_pvt_thread_mutex_lock( &desc.ad_type->sat_ad_mutex );
		/* check again now that we've locked */
		for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) {
			if (d2->ad_flags != desc.ad_flags)
				continue;
			if (d2->ad_tags.bv_len != desc.ad_tags.bv_len)
				continue;
			if (d2->ad_tags.bv_len == 0)
				break;
			if (strncasecmp(d2->ad_tags.bv_val, desc.ad_tags.bv_val,
				desc.ad_tags.bv_len) == 0)
				break;
		}
		if (d2) {
			ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex );
			break;
		}

		/* Allocate a single contiguous block. If there are no
		 * options, we just need space for the AttrDesc structure.
		 * Otherwise, we need to tack on the full name length +
		 * options length, + maybe tagging options length again.
		 */
		if (desc.ad_tags.bv_len || desc.ad_flags != SLAP_DESC_NONE) {
			dlen = desc.ad_type->sat_cname.bv_len + 1;
			if (desc.ad_tags.bv_len) {
				dlen += 1 + desc.ad_tags.bv_len;
			}
			if ( slap_ad_is_binary( &desc ) ) {
				dlen += 1 + STRLENOF(";binary") + desc.ad_tags.bv_len;
			}
		}

		d2 = ch_malloc(sizeof(AttributeDescription) + dlen);
		d2->ad_next = NULL;
		d2->ad_type = desc.ad_type;
		d2->ad_flags = desc.ad_flags;
		d2->ad_cname.bv_len = desc.ad_type->sat_cname.bv_len;
		d2->ad_tags.bv_len = desc.ad_tags.bv_len;
		ldap_pvt_thread_mutex_lock( &ad_index_mutex );
		d2->ad_index = ++ad_count;
		ldap_pvt_thread_mutex_unlock( &ad_index_mutex );

		if (dlen == 0) {
			d2->ad_cname.bv_val = d2->ad_type->sat_cname.bv_val;
			d2->ad_tags.bv_val = NULL;
		} else {
			char *cp, *op, *lp;
			int j;
			d2->ad_cname.bv_val = (char *)(d2+1);
			strcpy(d2->ad_cname.bv_val, d2->ad_type->sat_cname.bv_val);
			cp = d2->ad_cname.bv_val + d2->ad_cname.bv_len;
			if( slap_ad_is_binary( &desc ) ) {
				op = cp;
				lp = NULL;
				if( desc.ad_tags.bv_len ) {
					lp = desc.ad_tags.bv_val;
					while( strncasecmp(lp, "binary", STRLENOF("binary")) < 0
					       && (lp = strchr( lp, ';' )) != NULL )
						++lp;
					if( lp != desc.ad_tags.bv_val ) {
						*cp++ = ';';
						j = (lp
						     ? (unsigned) (lp - desc.ad_tags.bv_val - 1)
						     : strlen( desc.ad_tags.bv_val ));
						cp = lutil_strncopy(cp, desc.ad_tags.bv_val, j);
					}
				}
				cp = lutil_strcopy(cp, ";binary");
				if( lp != NULL ) {
					*cp++ = ';';
					cp = lutil_strcopy(cp, lp);
				}
				d2->ad_cname.bv_len = cp - d2->ad_cname.bv_val;
				if( desc.ad_tags.bv_len )
					ldap_pvt_str2lower(op);
				j = 1;
			} else {
				j = 0;
			}
			if( desc.ad_tags.bv_len ) {
				lp = d2->ad_cname.bv_val + d2->ad_cname.bv_len + j;
				if ( j == 0 )
					*lp++ = ';';
				d2->ad_tags.bv_val = lp;
				strcpy(lp, desc.ad_tags.bv_val);
				ldap_pvt_str2lower(lp);
				if( j == 0 )
					d2->ad_cname.bv_len += 1 + desc.ad_tags.bv_len;
			}
		}
		/* Add new desc to list. We always want the bare Desc with
		 * no options to stay at the head of the list, assuming
		 * that one will be used most frequently.
		 */
		if (desc.ad_type->sat_ad == NULL || dlen == 0) {
			d2->ad_next = desc.ad_type->sat_ad;
			desc.ad_type->sat_ad = d2;
		} else {
			d2->ad_next = desc.ad_type->sat_ad->ad_next;
			desc.ad_type->sat_ad->ad_next = d2;
		}
		ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex );
	}

	if( *ad == NULL ) {
		*ad = d2;
	} else {
		**ad = *d2;
	}

	return LDAP_SUCCESS;
}
Exemplo n.º 22
0
static int
constraint_cf_gen( ConfigArgs *c )
{
	slap_overinst *on = (slap_overinst *)(c->bi);
	constraint *cn = on->on_bi.bi_private, *cp;
	struct berval bv;
	int i, rc = 0;
	constraint ap = { NULL };
	const char *text = NULL;
	
	switch ( c->op ) {
	case SLAP_CONFIG_EMIT:
		switch (c->type) {
		case CONSTRAINT_ATTRIBUTE:
			for (cp=cn; cp; cp=cp->ap_next) {
				char *s;
				char *tstr = NULL;
				int quotes = 0;
				int j;

				bv.bv_len = STRLENOF("  ");
				for (j = 0; cp->ap[j]; j++) {
					bv.bv_len += cp->ap[j]->ad_cname.bv_len;
				}

				/* room for commas */
				bv.bv_len += j - 1;

				if (cp->re) {
					tstr = REGEX_STR;
				} else if (cp->lud) {
					tstr = URI_STR;
					quotes = 1;
				} else if (cp->set) {
					tstr = SET_STR;
					quotes = 1;
				} else if (cp->size) {
					tstr = SIZE_STR;
				} else if (cp->count) {
					tstr = COUNT_STR;
				}

				bv.bv_len += strlen(tstr);
				bv.bv_len += cp->val.bv_len + 2*quotes;

				if (cp->restrict_lud != NULL) {
					bv.bv_len += cp->restrict_val.bv_len + STRLENOF(" restrict=\"\"");
				}

				s = bv.bv_val = ch_malloc(bv.bv_len + 1);

				s = lutil_strncopy( s, cp->ap[0]->ad_cname.bv_val, cp->ap[0]->ad_cname.bv_len );
				for (j = 1; cp->ap[j]; j++) {
					*s++ = ',';
					s = lutil_strncopy( s, cp->ap[j]->ad_cname.bv_val, cp->ap[j]->ad_cname.bv_len );
				}
				*s++ = ' ';
				s = lutil_strcopy( s, tstr );
				*s++ = ' ';
				if ( quotes ) *s++ = '"';
				s = lutil_strncopy( s, cp->val.bv_val, cp->val.bv_len );
				if ( quotes ) *s++ = '"';
				if (cp->restrict_lud != NULL) {
					s = lutil_strcopy( s, " restrict=\"" );
					s = lutil_strncopy( s, cp->restrict_val.bv_val, cp->restrict_val.bv_len );
					*s++ = '"';
				}
				*s = '\0';

				rc = value_add_one( &c->rvalue_vals, &bv );
				if (rc == LDAP_SUCCESS)
					rc = value_add_one( &c->rvalue_nvals, &bv );
				ch_free(bv.bv_val);
				if (rc) return rc;
			}
			break;
		default:
			abort();
			break;
		}
		break;
	case LDAP_MOD_DELETE:
		switch (c->type) {
		case CONSTRAINT_ATTRIBUTE:
			if (!cn) break; /* nothing to do */
					
			if (c->valx < 0) {
				/* zap all constraints */
				while (cn) {
					cp = cn->ap_next;
					constraint_free( cn, 1 );
					cn = cp;
				}
						
				on->on_bi.bi_private = NULL;
			} else {
				constraint **cpp;
						
				/* zap constraint numbered 'valx' */
				for(i=0, cp = cn, cpp = &cn;
					(cp) && (i<c->valx);
					i++, cpp = &cp->ap_next, cp = *cpp);

				if (cp) {
					/* zap cp, and join cpp to cp->ap_next */
					*cpp = cp->ap_next;
					constraint_free( cp, 1 );
				}
				on->on_bi.bi_private = cn;
			}
			break;

		default:
			abort();
			break;
		}
		break;
	case SLAP_CONFIG_ADD:
	case LDAP_MOD_ADD:
		switch (c->type) {
		case CONSTRAINT_ATTRIBUTE: {
			int j;
			char **attrs = ldap_str2charray( c->argv[1], "," );

			for ( j = 0; attrs[j]; j++)
				/* just count */ ;
			ap.ap = ch_calloc( sizeof(AttributeDescription*), j + 1 );
			for ( j = 0; attrs[j]; j++) {
				if ( slap_str2ad( attrs[j], &ap.ap[j], &text ) ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s <%s>: %s\n", c->argv[0], attrs[j], text );
					rc = ARG_BAD_CONF;
					goto done;
				}
			}

			if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) {
				int err;
			
				ap.re = ch_malloc( sizeof(regex_t) );
				if ((err = regcomp( ap.re,
					c->argv[3], REG_EXTENDED )) != 0) {
					char errmsg[1024];
							
					regerror( err, ap.re, errmsg, sizeof(errmsg) );
					ch_free(ap.re);
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s %s: Illegal regular expression \"%s\": Error %s",
						c->argv[0], c->argv[1], c->argv[3], errmsg);
					ap.re = NULL;
					rc = ARG_BAD_CONF;
					goto done;
				}
				ber_str2bv( c->argv[3], 0, 1, &ap.val );
			} else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) {
				size_t size;

				if ( ( size = atoi(c->argv[3]) ) != 0 )
					ap.size = size;	
			} else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) {
				size_t count;

				if ( ( count = atoi(c->argv[3]) ) != 0 )
					ap.count = count;	
			} else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) {
				int err;
			
				err = ldap_url_parse(c->argv[3], &ap.lud);
				if ( err != LDAP_URL_SUCCESS ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s %s: Invalid URI \"%s\"",
						c->argv[0], c->argv[1], c->argv[3]);
					rc = ARG_BAD_CONF;
					goto done;
				}

				if (ap.lud->lud_host != NULL) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s %s: unsupported hostname in URI \"%s\"",
						c->argv[0], c->argv[1], c->argv[3]);
					ldap_free_urldesc(ap.lud);
					rc = ARG_BAD_CONF;
					goto done;
				}

				for ( i=0; ap.lud->lud_attrs[i]; i++);
				/* FIXME: This is worthless without at least one attr */
				if ( i ) {
					ap.attrs = ch_malloc( (i+1)*sizeof(AttributeDescription *));
					for ( i=0; ap.lud->lud_attrs[i]; i++) {
						ap.attrs[i] = NULL;
						if ( slap_str2ad( ap.lud->lud_attrs[i], &ap.attrs[i], &text ) ) {
							ch_free( ap.attrs );
							snprintf( c->cr_msg, sizeof( c->cr_msg ),
								"%s <%s>: %s\n", c->argv[0], ap.lud->lud_attrs[i], text );
							rc = ARG_BAD_CONF;
							goto done;
						}
					}
					ap.attrs[i] = NULL;
				}

				if (ap.lud->lud_dn == NULL) {
					ap.lud->lud_dn = ch_strdup("");
				} else {
					struct berval dn, ndn;

					ber_str2bv( ap.lud->lud_dn, 0, 0, &dn );
					if (dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) ) {
						/* cleanup */
						snprintf( c->cr_msg, sizeof( c->cr_msg ),
							"%s %s: URI %s DN normalization failed",
							c->argv[0], c->argv[1], c->argv[3] );
						Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
							   "%s: %s\n", c->log, c->cr_msg, 0 );
						rc = ARG_BAD_CONF;
						goto done;
					}
					ldap_memfree( ap.lud->lud_dn );
					ap.lud->lud_dn = ndn.bv_val;
				}

				if (ap.lud->lud_filter == NULL) {
					ap.lud->lud_filter = ch_strdup("objectClass=*");
				} else if ( ap.lud->lud_filter[0] == '(' ) {
					ber_len_t len = strlen( ap.lud->lud_filter );
					if ( ap.lud->lud_filter[len - 1] != ')' ) {
						snprintf( c->cr_msg, sizeof( c->cr_msg ),
							"%s %s: invalid URI filter: %s",
							c->argv[0], c->argv[1], ap.lud->lud_filter );
						rc = ARG_BAD_CONF;
						goto done;
					}
					AC_MEMCPY( &ap.lud->lud_filter[0], &ap.lud->lud_filter[1], len - 2 );
					ap.lud->lud_filter[len - 2] = '\0';
				}

				ber_str2bv( c->argv[3], 0, 1, &ap.val );

			} else if ( strcasecmp( c->argv[2], SET_STR ) == 0 ) {
				ap.set = 1;
				ber_str2bv( c->argv[3], 0, 1, &ap.val );

			} else {
				snprintf( c->cr_msg, sizeof( c->cr_msg ),
					"%s %s: Unknown constraint type: %s",
					c->argv[0], c->argv[1], c->argv[2] );
				rc = ARG_BAD_CONF;
				goto done;
			}

			if ( c->argc > 4 ) {
				int argidx;

				for ( argidx = 4; argidx < c->argc; argidx++ ) {
					if ( strncasecmp( c->argv[argidx], "restrict=", STRLENOF("restrict=") ) == 0 ) {
						int err;
						char *arg = c->argv[argidx] + STRLENOF("restrict=");

						err = ldap_url_parse(arg, &ap.restrict_lud);
						if ( err != LDAP_URL_SUCCESS ) {
							snprintf( c->cr_msg, sizeof( c->cr_msg ),
								"%s %s: Invalid restrict URI \"%s\"",
								c->argv[0], c->argv[1], arg);
							rc = ARG_BAD_CONF;
							goto done;
						}

						if (ap.restrict_lud->lud_host != NULL) {
							snprintf( c->cr_msg, sizeof( c->cr_msg ),
								"%s %s: unsupported hostname in restrict URI \"%s\"",
								c->argv[0], c->argv[1], arg);
							rc = ARG_BAD_CONF;
							goto done;
						}

						if ( ap.restrict_lud->lud_attrs != NULL ) {
							if ( ap.restrict_lud->lud_attrs[0] != '\0' ) {
								snprintf( c->cr_msg, sizeof( c->cr_msg ),
									"%s %s: attrs not allowed in restrict URI %s\n",
									c->argv[0], c->argv[1], arg);
								rc = ARG_BAD_CONF;
								goto done;
							}
							ldap_memvfree((void *)ap.restrict_lud->lud_attrs);
							ap.restrict_lud->lud_attrs = NULL;
						}

						if (ap.restrict_lud->lud_dn != NULL) {
							if (ap.restrict_lud->lud_dn[0] == '\0') {
								ldap_memfree(ap.restrict_lud->lud_dn);
								ap.restrict_lud->lud_dn = NULL;

							} else {
								struct berval dn, ndn;
								int j;

								ber_str2bv(ap.restrict_lud->lud_dn, 0, 0, &dn);
								if (dnNormalize(0, NULL, NULL, &dn, &ndn, NULL)) {
									/* cleanup */
									snprintf( c->cr_msg, sizeof( c->cr_msg ),
										"%s %s: restrict URI %s DN normalization failed",
										c->argv[0], c->argv[1], arg );
									rc = ARG_BAD_CONF;
									goto done;
								}

								assert(c->be != NULL);
								if (c->be->be_nsuffix == NULL) {
									snprintf( c->cr_msg, sizeof( c->cr_msg ),
										"%s %s: restrict URI requires suffix",
										c->argv[0], c->argv[1] );
									rc = ARG_BAD_CONF;
									goto done;
								}

								for ( j = 0; !BER_BVISNULL(&c->be->be_nsuffix[j]); j++) {
									if (dnIsSuffix(&ndn, &c->be->be_nsuffix[j])) break;
								}

								if (BER_BVISNULL(&c->be->be_nsuffix[j])) {
									/* error */
									snprintf( c->cr_msg, sizeof( c->cr_msg ),
										"%s %s: restrict URI DN %s not within database naming context(s)",
										c->argv[0], c->argv[1], dn.bv_val );
									rc = ARG_BAD_CONF;
									goto done;
								}

								ap.restrict_ndn = ndn;
							}
						}

						if (ap.restrict_lud->lud_filter != NULL) {
							ap.restrict_filter = str2filter(ap.restrict_lud->lud_filter);
							if (ap.restrict_filter == NULL) {
								/* error */
								snprintf( c->cr_msg, sizeof( c->cr_msg ),
									"%s %s: restrict URI filter %s invalid",
									c->argv[0], c->argv[1], ap.restrict_lud->lud_filter );
								rc = ARG_BAD_CONF;
								goto done;
							}
						}

						ber_str2bv(c->argv[argidx], 0, 1, &ap.restrict_val);

					} else {
						/* cleanup */
						snprintf( c->cr_msg, sizeof( c->cr_msg ),
							"%s %s: unrecognized arg #%d (%s)",
							c->argv[0], c->argv[1], argidx, c->argv[argidx] );
						rc = ARG_BAD_CONF;
						goto done;
					}
				}
			}

done:;
			if ( rc == LDAP_SUCCESS ) {
				constraint *a2 = ch_calloc( sizeof(constraint), 1 );
				a2->ap_next = on->on_bi.bi_private;
				a2->ap = ap.ap;
				a2->re = ap.re;
				a2->val = ap.val;
				a2->lud = ap.lud;
				a2->set = ap.set;
				a2->size = ap.size;
				a2->count = ap.count;
				if ( a2->lud ) {
					ber_str2bv(a2->lud->lud_dn, 0, 0, &a2->dn);
					ber_str2bv(a2->lud->lud_filter, 0, 0, &a2->filter);
				}
				a2->attrs = ap.attrs;
				a2->restrict_lud = ap.restrict_lud;
				a2->restrict_ndn = ap.restrict_ndn;
				a2->restrict_filter = ap.restrict_filter;
				a2->restrict_val = ap.restrict_val;
				on->on_bi.bi_private = a2;

			} else {
				Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
					   "%s: %s\n", c->log, c->cr_msg, 0 );
				constraint_free( &ap, 0 );
			}

			ldap_memvfree((void**)attrs);
			} break;
		default:
			abort();
			break;
		}
		break;
	default:
		abort();
	}

	return rc;
}
Exemplo n.º 23
0
/* We add two elements to the DN2ID database - a data item under the parent's
 * entryID containing the child's RDN and entryID, and an item under the
 * child's entryID containing the parent's entryID.
 */
int
hdb_dn2id_add(
	Operation	*op,
	DB_TXN *txn,
	EntryInfo	*eip,
	Entry		*e )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	DB *db = bdb->bi_dn2id->bdi_db;
	DBT		key, data;
	ID		nid;
	int		rc, rlen, nrlen;
	diskNode *d;
	char *ptr;

	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_add 0x%lx: \"%s\"\n",
		e->e_id, e->e_ndn, 0 );

	nrlen = dn_rdnlen( op->o_bd, &e->e_nname );
	if (nrlen) {
		rlen = dn_rdnlen( op->o_bd, &e->e_name );
	} else {
		nrlen = e->e_nname.bv_len;
		rlen = e->e_name.bv_len;
	}

	d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx);
	d->nrdnlen[1] = nrlen & 0xff;
	d->nrdnlen[0] = (nrlen >> 8) | 0x80;
	ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );
	*ptr++ = '\0';
	ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );
	*ptr++ = '\0';
	BDB_ID2DISK( e->e_id, ptr );

	DBTzero(&key);
	DBTzero(&data);
	key.size = sizeof(ID);
	key.flags = DB_DBT_USERMEM;
	BDB_ID2DISK( eip->bei_id, &nid );

	key.data = &nid;

	/* Need to make dummy root node once. Subsequent attempts
	 * will fail harmlessly.
	 */
	if ( eip->bei_id == 0 ) {
		diskNode dummy = {{0, 0}, "", "", ""};
		data.data = &dummy;
		data.size = sizeof(diskNode);
		data.flags = DB_DBT_USERMEM;

		db->put( db, txn, &key, &data, DB_NODUPDATA );
	}

	data.data = d;
	data.size = sizeof(diskNode) + rlen + nrlen;
	data.flags = DB_DBT_USERMEM;

	rc = db->put( db, txn, &key, &data, DB_NODUPDATA );

	if (rc == 0) {
		BDB_ID2DISK( e->e_id, &nid );
		BDB_ID2DISK( eip->bei_id, ptr );
		d->nrdnlen[0] ^= 0x80;

		rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
	}

	/* Update all parents' IDL cache entries */
	if ( rc == 0 && bdb->bi_idl_cache_size ) {
		ID tmp[2];
		char *ptr = ((char *)&tmp[1])-1;
		key.data = ptr;
		key.size = sizeof(ID)+1;
		tmp[1] = eip->bei_id;
		*ptr = DN_ONE_PREFIX;
		bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
		if ( eip->bei_parent ) {
			*ptr = DN_SUBTREE_PREFIX;
			for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
				tmp[1] = eip->bei_id;
				bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
			}
			/* Handle DB with empty suffix */
			if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
				tmp[1] = eip->bei_id;
				bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
			}
		}
	}

	op->o_tmpfree( d, op->o_tmpmemctx );
	Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 );

	return rc;
}
Exemplo n.º 24
0
static int
dl_cfgen( ConfigArgs *c )
{
	slap_overinst	*on = (slap_overinst *)c->bi;
	dynlist_info_t	*dli = (dynlist_info_t *)on->on_bi.bi_private;

	int		rc = 0, i;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		switch( c->type ) {
		case DL_ATTRSET:
			for ( i = 0; dli; i++, dli = dli->dli_next ) {
				struct berval	bv;
				char		*ptr = c->cr_msg;
				dynlist_map_t	*dlm;

				assert( dli->dli_oc != NULL );
				assert( dli->dli_ad != NULL );

				/* FIXME: check buffer overflow! */
				ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
					SLAP_X_ORDERED_FMT "%s", i,
					dli->dli_oc->soc_cname.bv_val );

				if ( !BER_BVISNULL( &dli->dli_uri ) ) {
					*ptr++ = ' ';
					*ptr++ = '"';
					ptr = lutil_strncopy( ptr, dli->dli_uri.bv_val,
						dli->dli_uri.bv_len );
					*ptr++ = '"';
				}

				*ptr++ = ' ';
				ptr = lutil_strncopy( ptr, dli->dli_ad->ad_cname.bv_val,
					dli->dli_ad->ad_cname.bv_len );

				for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
					ptr[ 0 ] = ' ';
					ptr++;
					if ( dlm->dlm_mapped_ad ) {
						ptr = lutil_strcopy( ptr, dlm->dlm_mapped_ad->ad_cname.bv_val );
						ptr[ 0 ] = ':';
						ptr++;
					}
						
					ptr = lutil_strcopy( ptr, dlm->dlm_member_ad->ad_cname.bv_val );
				}

				bv.bv_val = c->cr_msg;
				bv.bv_len = ptr - bv.bv_val;
				value_add_one( &c->rvalue_vals, &bv );
			}
			break;

		case DL_ATTRPAIR_COMPAT:
		case DL_ATTRPAIR:
			rc = 1;
			break;

		default:
			rc = 1;
			break;
		}

		return rc;

	} else if ( c->op == LDAP_MOD_DELETE ) {
		switch( c->type ) {
		case DL_ATTRSET:
			if ( c->valx < 0 ) {
				dynlist_info_t	*dli_next;

				for ( dli_next = dli; dli_next; dli = dli_next ) {
					dynlist_map_t *dlm = dli->dli_dlm;
					dynlist_map_t *dlm_next;

					dli_next = dli->dli_next;

					if ( !BER_BVISNULL( &dli->dli_uri ) ) {
						ch_free( dli->dli_uri.bv_val );
					}

					if ( dli->dli_lud != NULL ) {
						ldap_free_urldesc( dli->dli_lud );
					}

					if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
						ber_memfree( dli->dli_uri_nbase.bv_val );
					}

					if ( dli->dli_uri_filter != NULL ) {
						filter_free( dli->dli_uri_filter );
					}

					ch_free( dli->dli_default_filter.bv_val );

					while ( dlm != NULL ) {
						dlm_next = dlm->dlm_next;
						ch_free( dlm );
						dlm = dlm_next;
					}
					ch_free( dli );
				}

				on->on_bi.bi_private = NULL;

			} else {
				dynlist_info_t	**dlip;
				dynlist_map_t *dlm;
				dynlist_map_t *dlm_next;

				for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private;
					i < c->valx; i++ )
				{
					if ( *dlip == NULL ) {
						return 1;
					}
					dlip = &(*dlip)->dli_next;
				}

				dli = *dlip;
				*dlip = dli->dli_next;

				if ( !BER_BVISNULL( &dli->dli_uri ) ) {
					ch_free( dli->dli_uri.bv_val );
				}

				if ( dli->dli_lud != NULL ) {
					ldap_free_urldesc( dli->dli_lud );
				}

				if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
					ber_memfree( dli->dli_uri_nbase.bv_val );
				}

				if ( dli->dli_uri_filter != NULL ) {
					filter_free( dli->dli_uri_filter );
				}

				ch_free( dli->dli_default_filter.bv_val );

				dlm = dli->dli_dlm;
				while ( dlm != NULL ) {
					dlm_next = dlm->dlm_next;
					ch_free( dlm );
					dlm = dlm_next;
				}
				ch_free( dli );

				dli = (dynlist_info_t *)on->on_bi.bi_private;
			}
			break;

		case DL_ATTRPAIR_COMPAT:
		case DL_ATTRPAIR:
			rc = 1;
			break;

		default:
			rc = 1;
			break;
		}

		return rc;
	}

	switch( c->type ) {
	case DL_ATTRSET: {
		dynlist_info_t		**dlip,
					*dli_next = NULL;
		ObjectClass		*oc = NULL;
		AttributeDescription	*ad = NULL;
		int			attridx = 2;
		LDAPURLDesc		*lud = NULL;
		struct berval		nbase = BER_BVNULL;
		Filter			*filter = NULL;
		struct berval		uri = BER_BVNULL;
		dynlist_map_t           *dlm = NULL, *dlml = NULL;
		const char		*text;

		oc = oc_find( c->argv[ 1 ] );
		if ( oc == NULL ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
				"unable to find ObjectClass \"%s\"",
				c->argv[ 1 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		if ( strncasecmp( c->argv[ attridx ], "ldap://", STRLENOF("ldap://") ) == 0 ) {
			if ( ldap_url_parse( c->argv[ attridx ], &lud ) != LDAP_URL_SUCCESS ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
					"unable to parse URI \"%s\"",
					c->argv[ attridx ] );
				rc = 1;
				goto done_uri;
			}

			if ( lud->lud_host != NULL ) {
				if ( lud->lud_host[0] == '\0' ) {
					ch_free( lud->lud_host );
					lud->lud_host = NULL;

				} else {
					snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
						"host not allowed in URI \"%s\"",
						c->argv[ attridx ] );
					rc = 1;
					goto done_uri;
				}
			}

			if ( lud->lud_attrs != NULL ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
					"attrs not allowed in URI \"%s\"",
					c->argv[ attridx ] );
				rc = 1;
				goto done_uri;
			}

			if ( lud->lud_exts != NULL ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
					"extensions not allowed in URI \"%s\"",
					c->argv[ attridx ] );
				rc = 1;
				goto done_uri;
			}

			if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' ) {
				struct berval dn;
				ber_str2bv( lud->lud_dn, 0, 0, &dn );
				rc = dnNormalize( 0, NULL, NULL, &dn, &nbase, NULL );
				if ( rc != LDAP_SUCCESS ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
						"DN normalization failed in URI \"%s\"",
						c->argv[ attridx ] );
					goto done_uri;
				}
			}

			if ( lud->lud_filter != NULL && lud->lud_filter[ 0 ] != '\0' ) {
				filter = str2filter( lud->lud_filter );
				if ( filter == NULL ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
						"filter parsing failed in URI \"%s\"",
						c->argv[ attridx ] );
					rc = 1;
					goto done_uri;
				}
			}

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

done_uri:;
			if ( rc ) {
				if ( lud ) {
					ldap_free_urldesc( lud );
				}

				if ( !BER_BVISNULL( &nbase ) ) {
					ber_memfree( nbase.bv_val );
				}

				if ( filter != NULL ) {
					filter_free( filter );
				}

				while ( dlm != NULL ) {
					dlml = dlm;
					dlm = dlm->dlm_next;
					ch_free( dlml );
				}

				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
					c->log, c->cr_msg, 0 );

				return rc;
			}

			attridx++;
		}

		rc = slap_str2ad( c->argv[ attridx ], &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
				"unable to find AttributeDescription \"%s\"",
				c->argv[ attridx ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			rc = 1;
			goto done_uri;
		}

		if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
				"AttributeDescription \"%s\" "
				"must be a subtype of \"labeledURI\"",
				c->argv[ attridx ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			rc = 1;
			goto done_uri;
		}

		attridx++;

		for ( i = attridx; i < c->argc; i++ ) {
			char *arg; 
			char *cp;
			AttributeDescription *member_ad = NULL;
			AttributeDescription *mapped_ad = NULL;
			dynlist_map_t *dlmp;


			/*
			 * If no mapped attribute is given, dn is used 
			 * for backward compatibility.
			 */
			arg = c->argv[i];
			if ( ( cp = strchr( arg, ':' ) ) != NULL ) {
				struct berval bv;
				ber_str2bv( arg, cp - arg, 0, &bv );
				rc = slap_bv2ad( &bv, &mapped_ad, &text );
				if ( rc != LDAP_SUCCESS ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						DYNLIST_USAGE
						"unable to find mapped AttributeDescription #%d \"%s\"\n",
						i - 3, c->argv[ i ] );
					Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
						c->log, c->cr_msg, 0 );
					rc = 1;
					goto done_uri;
				}
				arg = cp + 1;
			}

			rc = slap_str2ad( arg, &member_ad, &text );
			if ( rc != LDAP_SUCCESS ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ),
					DYNLIST_USAGE
					"unable to find AttributeDescription #%d \"%s\"\n",
					i - 3, c->argv[ i ] );
				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
					c->log, c->cr_msg, 0 );
				rc = 1;
				goto done_uri;
			}

			dlmp = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
			if ( dlm == NULL ) {
				dlm = dlmp;
			}
			dlmp->dlm_member_ad = member_ad;
			dlmp->dlm_mapped_ad = mapped_ad;
			dlmp->dlm_next = NULL;
		
			if ( dlml != NULL ) 
				dlml->dlm_next = dlmp;
			dlml = dlmp;
		}

		if ( c->valx > 0 ) {
			int	i;

			for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private;
				i < c->valx; i++ )
			{
				if ( *dlip == NULL ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						DYNLIST_USAGE
						"invalid index {%d}\n",
						c->valx );
					Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
						c->log, c->cr_msg, 0 );
					rc = 1;
					goto done_uri;
				}
				dlip = &(*dlip)->dli_next;
			}
			dli_next = *dlip;

		} else {
			for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
				*dlip; dlip = &(*dlip)->dli_next )
				/* goto last */;
		}

		*dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );

		(*dlip)->dli_oc = oc;
		(*dlip)->dli_ad = ad;
		(*dlip)->dli_dlm = dlm;
		(*dlip)->dli_next = dli_next;

		(*dlip)->dli_lud = lud;
		(*dlip)->dli_uri_nbase = nbase;
		(*dlip)->dli_uri_filter = filter;
		(*dlip)->dli_uri = uri;

		rc = dynlist_build_def_filter( *dlip );

		} break;

	case DL_ATTRPAIR_COMPAT:
		snprintf( c->cr_msg, sizeof( c->cr_msg ),
			"warning: \"attrpair\" only supported for limited "
			"backward compatibility with overlay \"dyngroup\"" );
		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
		/* fallthru */

	case DL_ATTRPAIR: {
		dynlist_info_t		**dlip;
		ObjectClass		*oc = NULL;
		AttributeDescription	*ad = NULL,
					*member_ad = NULL;
		const char		*text;

		oc = oc_find( "groupOfURLs" );
		if ( oc == NULL ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				"\"dynlist-attrpair <member-ad> <URL-ad>\": "
				"unable to find default ObjectClass \"groupOfURLs\"" );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				"\"dynlist-attrpair <member-ad> <URL-ad>\": "
				"unable to find AttributeDescription \"%s\"",
				c->argv[ 1 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				"\"dynlist-attrpair <member-ad> <URL-ad>\": "
				"unable to find AttributeDescription \"%s\"\n",
				c->argv[ 2 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				DYNLIST_USAGE
				"AttributeDescription \"%s\" "
				"must be a subtype of \"labeledURI\"",
				c->argv[ 2 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
			*dlip; dlip = &(*dlip)->dli_next )
		{
			/* 
			 * The same URL attribute / member attribute pair
			 * cannot be repeated, but we enforce this only 
			 * when the member attribute is unique. Performing
			 * the check for multiple values would require
			 * sorting and comparing the lists, which is left
			 * as a future improvement
			 */
			if ( (*dlip)->dli_ad == ad &&
			     (*dlip)->dli_dlm->dlm_next == NULL &&
			     member_ad == (*dlip)->dli_dlm->dlm_member_ad ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ),
					"\"dynlist-attrpair <member-ad> <URL-ad>\": "
					"URL attributeDescription \"%s\" already mapped.\n",
					ad->ad_cname.bv_val );
				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
					c->log, c->cr_msg, 0 );
#if 0
				/* make it a warning... */
				return 1;
#endif
			}
		}

		*dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );

		(*dlip)->dli_oc = oc;
		(*dlip)->dli_ad = ad;
		(*dlip)->dli_dlm = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
		(*dlip)->dli_dlm->dlm_member_ad = member_ad;
		(*dlip)->dli_dlm->dlm_mapped_ad = NULL;

		rc = dynlist_build_def_filter( *dlip );

		} break;

	default:
		rc = 1;
		break;
	}

	return rc;
}
Exemplo n.º 25
0
int
do_search(
    Operation	*op,	/* info about the op to which we're responding */
    SlapReply	*rs	/* all the response data we'll send */ )
{
	struct berval base = BER_BVNULL;
	ber_len_t	siz, off, i;

	Debug( LDAP_DEBUG_TRACE, "%s do_search\n",
		op->o_log_prefix, 0, 0 );
	/*
	 * Parse the search request.  It looks like this:
	 *
	 *	SearchRequest := [APPLICATION 3] SEQUENCE {
	 *		baseObject	DistinguishedName,
	 *		scope		ENUMERATED {
	 *			baseObject	(0),
	 *			singleLevel	(1),
	 *			wholeSubtree (2),
	 *          subordinate (3)  -- OpenLDAP extension
	 *		},
	 *		derefAliases	ENUMERATED {
	 *			neverDerefaliases	(0),
	 *			derefInSearching	(1),
	 *			derefFindingBaseObj	(2),
	 *			alwaysDerefAliases	(3)
	 *		},
	 *		sizelimit	INTEGER (0 .. 65535),
	 *		timelimit	INTEGER (0 .. 65535),
	 *		attrsOnly	BOOLEAN,
	 *		filter		Filter,
	 *		attributes	SEQUENCE OF AttributeType
	 *	}
	 */

	/* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
	if ( ber_scanf( op->o_ber, "{miiiib" /*}*/,
		&base, &op->ors_scope, &op->ors_deref, &op->ors_slimit,
	    &op->ors_tlimit, &op->ors_attrsonly ) == LBER_ERROR )
	{
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
		rs->sr_err = SLAPD_DISCONNECT;
		goto return_results;
	}

	if ( op->ors_tlimit < 0 || op->ors_tlimit > SLAP_MAX_LIMIT ) {
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid time limit" );
		goto return_results;
	}

	if ( op->ors_slimit < 0 || op->ors_slimit > SLAP_MAX_LIMIT ) {
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid size limit" );
		goto return_results;
	}

	switch( op->ors_scope ) {
	case LDAP_SCOPE_BASE:
	case LDAP_SCOPE_ONELEVEL:
	case LDAP_SCOPE_SUBTREE:
	case LDAP_SCOPE_SUBORDINATE:
		break;
	default:
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid scope" );
		goto return_results;
	}

	switch( op->ors_deref ) {
	case LDAP_DEREF_NEVER:
	case LDAP_DEREF_FINDING:
	case LDAP_DEREF_SEARCHING:
	case LDAP_DEREF_ALWAYS:
		break;
	default:
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid deref" );
		goto return_results;
	}

	rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn: \"%s\"\n",
			op->o_log_prefix, base.bv_val, 0 );
		send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
		goto return_results;
	}

	Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d",
		base.bv_val, op->ors_scope, op->ors_deref );
	Debug( LDAP_DEBUG_ARGS, "    %d %d %d\n",
		op->ors_slimit, op->ors_tlimit, op->ors_attrsonly);

	/* filter - returns a "normalized" version */
	rs->sr_err = get_filter( op, op->o_ber, &op->ors_filter, &rs->sr_text );
	if( rs->sr_err != LDAP_SUCCESS ) {
		if( rs->sr_err == SLAPD_DISCONNECT ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			send_ldap_disconnect( op, rs );
			rs->sr_err = SLAPD_DISCONNECT;
		} else {
			send_ldap_result( op, rs );
		}
		goto return_results;
	}
	filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
	
	Debug( LDAP_DEBUG_ARGS, "    filter: %s\n",
		!BER_BVISEMPTY( &op->ors_filterstr ) ? op->ors_filterstr.bv_val : "empty", 0, 0 );

	/* attributes */
	siz = sizeof(AttributeName);
	off = offsetof(AttributeName,an_name);
	if ( ber_scanf( op->o_ber, "{M}}", &op->ors_attrs, &siz, off ) == LBER_ERROR ) {
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding attrs error" );
		rs->sr_err = SLAPD_DISCONNECT;
		goto return_results;
	}
	for ( i=0; i<siz; i++ ) {
		const char *dummy;	/* ignore msgs from bv2ad */
		op->ors_attrs[i].an_desc = NULL;
		op->ors_attrs[i].an_oc = NULL;
		op->ors_attrs[i].an_flags = 0;
		if ( slap_bv2ad( &op->ors_attrs[i].an_name,
			&op->ors_attrs[i].an_desc, &dummy ) != LDAP_SUCCESS )
		{
			if ( slap_bv2undef_ad( &op->ors_attrs[i].an_name,
				&op->ors_attrs[i].an_desc, &dummy,
				SLAP_AD_PROXIED|SLAP_AD_NOINSERT ) )
			{
				struct berval *bv = &op->ors_attrs[i].an_name;

				/* RFC 4511 LDAPv3: All User Attributes */
				if ( bvmatch( bv, slap_bv_all_user_attrs ) ) {
					continue;
				}

				/* RFC 3673 LDAPv3: All Operational Attributes */
				if ( bvmatch( bv, slap_bv_all_operational_attrs ) ) {
					continue;
				}

				/* RFC 4529 LDAP: Requesting Attributes by Object Class */
				if ( bv->bv_len > 1 && bv->bv_val[0] == '@' ) {
					/* FIXME: check if remaining is valid oc name? */
					continue;
				}

				/* add more "exceptions" to RFC 4511 4.5.1.8. */

				/* invalid attribute description? remove */
				if ( ad_keystring( bv ) ) {
					/* NOTE: parsed in-place, don't modify;
					 * rather add "1.1", which must be ignored */
					BER_BVSTR( &op->ors_attrs[i].an_name, LDAP_NO_ATTRS );
				}

				/* otherwise leave in place... */
			}
		}
	}

	if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n",
			op->o_log_prefix, 0, 0 );
		goto return_results;
	}

	Debug( LDAP_DEBUG_ARGS, "    attrs:", 0, 0, 0 );

	if ( siz != 0 ) {
		for ( i = 0; i<siz; i++ ) {
			Debug( LDAP_DEBUG_ARGS, " %s", op->ors_attrs[i].an_name.bv_val, 0, 0 );
		}
	}

	Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );

	if ( StatslogTest( LDAP_DEBUG_STATS ) ) {
		char abuf[BUFSIZ/2], *ptr = abuf;
		unsigned len = 0, alen;

		sprintf(abuf, "scope=%d deref=%d", op->ors_scope, op->ors_deref);
		Statslog( LDAP_DEBUG_STATS,
		        "%s SRCH base=\"%s\" %s filter=\"%s\"\n",
		        op->o_log_prefix, op->o_req_dn.bv_val, abuf,
		        op->ors_filterstr.bv_val, 0 );

		for ( i = 0; i<siz; i++ ) {
			alen = op->ors_attrs[i].an_name.bv_len;
			if (alen >= sizeof(abuf)) {
				alen = sizeof(abuf)-1;
			}
			if (len && (len + 1 + alen >= sizeof(abuf))) {
				Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n",
				    op->o_log_prefix, abuf, 0, 0, 0 );
				len = 0;
				ptr = abuf;
			}
			if (len) {
				*ptr++ = ' ';
				len++;
			}
			ptr = lutil_strncopy(ptr, op->ors_attrs[i].an_name.bv_val, alen);
			len += alen;
			*ptr = '\0';
		}
		if (len) {
			Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n",
	    			op->o_log_prefix, abuf, 0, 0, 0 );
		}
	}

	op->o_bd = frontendDB;
	rs->sr_err = frontendDB->be_search( op, rs );

return_results:;
	if ( !BER_BVISNULL( &op->o_req_dn ) ) {
		slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx );
	}
	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
		slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx );
	}
	if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
		op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	}
	if ( op->ors_filter != NULL) {
		filter_free_x( op, op->ors_filter, 1 );
	}
	if ( op->ors_attrs != NULL ) {
		op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx );
	}

	return rs->sr_err;
}
Exemplo n.º 26
0
/* return last found ID in *id if no match
 * If mc is provided, it will be left pointing to the RDN's
 * record under the parent's ID. If nsubs is provided, return
 * the number of entries in this entry's subtree.
 */
int
mdb_dn2id(
	Operation	*op,
	MDB_txn *txn,
	MDB_cursor	*mc,
	struct berval	*in,
	ID	*id,
	ID	*nsubs,
	struct berval	*matched,
	struct berval	*nmatched )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_cursor *cursor;
	MDB_dbi dbi = mdb->mi_dn2id;
	MDB_val		key, data;
	int		rc = 0, nrlen;
	diskNode *d;
	char	*ptr;
	char dn[SLAP_LDAPDN_MAXLEN];
	ID pid, nid;
	struct berval tmp;

	Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2id(\"%s\")\n", in->bv_val ? in->bv_val : "" );

	if ( matched ) {
		matched->bv_val = dn + sizeof(dn) - 1;
		matched->bv_len = 0;
		*matched->bv_val-- = '\0';
	}
	if ( nmatched ) {
		nmatched->bv_len = 0;
		nmatched->bv_val = 0;
	}

	if ( !in->bv_len ) {
		*id = 0;
		nid = 0;
		goto done;
	}

	tmp = *in;

	if ( op->o_bd->be_nsuffix[0].bv_len ) {
		nrlen = tmp.bv_len - op->o_bd->be_nsuffix[0].bv_len;
		tmp.bv_val += nrlen;
		tmp.bv_len = op->o_bd->be_nsuffix[0].bv_len;
	} else {
		for ( ptr = tmp.bv_val + tmp.bv_len - 1; ptr >= tmp.bv_val; ptr-- )
			if (DN_SEPARATOR(*ptr))
				break;
		ptr++;
		tmp.bv_len -= ptr - tmp.bv_val;
		tmp.bv_val = ptr;
	}
	nid = 0;
	key.mv_size = sizeof(ID);

	if ( mc ) {
		cursor = mc;
	} else {
		rc = mdb_cursor_open( txn, dbi, &cursor );
		if ( rc ) goto done;
	}

	for (;;) {
		key.mv_data = &pid;
		pid = nid;

		data.mv_size = sizeof(diskNode) + tmp.bv_len;
		d = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
		d->nrdnlen[1] = tmp.bv_len & 0xff;
		d->nrdnlen[0] = (tmp.bv_len >> 8) | 0x80;
		ptr = lutil_strncopy( d->nrdn, tmp.bv_val, tmp.bv_len );
		*ptr = '\0';
		data.mv_data = d;
		rc = mdb_cursor_get( cursor, &key, &data, MDB_GET_BOTH );
		op->o_tmpfree( d, op->o_tmpmemctx );
		if ( rc )
			break;
		ptr = (char *) data.mv_data + data.mv_size - 2*sizeof(ID);
		memcpy( &nid, ptr, sizeof(ID));

		/* grab the non-normalized RDN */
		if ( matched ) {
			int rlen;
			d = data.mv_data;
			rlen = data.mv_size - sizeof(diskNode) - tmp.bv_len - sizeof(ID);
			matched->bv_len += rlen;
			matched->bv_val -= rlen + 1;
			ptr = lutil_strcopy( matched->bv_val, d->rdn + tmp.bv_len );
			if ( pid ) {
				*ptr = ',';
				matched->bv_len++;
			}
		}
		if ( nmatched ) {
			nmatched->bv_val = tmp.bv_val;
		}

		if ( tmp.bv_val > in->bv_val ) {
			for (ptr = tmp.bv_val - 2; ptr > in->bv_val &&
				!DN_SEPARATOR(*ptr); ptr--)	/* empty */;
			if ( ptr >= in->bv_val ) {
				if (DN_SEPARATOR(*ptr)) ptr++;
				tmp.bv_len = tmp.bv_val - ptr - 1;
				tmp.bv_val = ptr;
			}
		} else {
			break;
		}
	}
	*id = nid;
	/* return subtree count if requested */
	if ( !rc && nsubs ) {
		ptr = (char *)data.mv_data + data.mv_size - sizeof(ID);
		memcpy( nsubs, ptr, sizeof( ID ));
	}
	if ( !mc )
		mdb_cursor_close( cursor );
done:
	if ( matched ) {
		if ( matched->bv_len ) {
			ptr = op->o_tmpalloc( matched->bv_len+1, op->o_tmpmemctx );
			strcpy( ptr, matched->bv_val );
			matched->bv_val = ptr;
		} else {
			if ( BER_BVISEMPTY( &op->o_bd->be_nsuffix[0] ) && !nid ) {
				ber_dupbv( matched, (struct berval *)&slap_empty_bv );
			} else {
				matched->bv_val = NULL;
			}
		}
	}
	if ( nmatched ) {
		if ( nmatched->bv_val ) {
			nmatched->bv_len = in->bv_len - (nmatched->bv_val - in->bv_val);
		} else {
			*nmatched = slap_empty_bv;
		}
	}

	if( rc != 0 ) {
		Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: get failed: %s (%d)\n",
			mdb_strerror( rc ), rc );
	} else {
		Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: got id=0x%lx\n", nid );
	}

	return rc;
}
Exemplo n.º 27
0
static int
OpenLDAPaciPrettyNormal(
	struct berval	*val,
	struct berval	*out,
	void		*ctx,
	int		normalize )
{
	struct berval	oid = BER_BVNULL,
			scope = BER_BVNULL,
			rights = BER_BVNULL,
			nrights = BER_BVNULL,
			type = BER_BVNULL,
			ntype = BER_BVNULL,
			subject = BER_BVNULL,
			nsubject = BER_BVNULL;
	int		idx,
			rc = LDAP_SUCCESS,
			freesubject = 0,
			freetype = 0;
	char		*ptr;

	BER_BVZERO( out );

	if ( BER_BVISEMPTY( val ) ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: value is empty\n" );
		return LDAP_INVALID_SYNTAX;
	}

	/* oid: if valid, it's already normalized */
	if ( acl_get_part( val, 0, '#', &oid ) < 0 ||
		numericoidValidate( NULL, &oid ) != LDAP_SUCCESS )
	{
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid oid '%s'\n", oid.bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	/* scope: normalize by replacing with OpenLDAPaciscopes */
	if ( acl_get_part( val, 1, '#', &scope ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing scope in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	idx = bv_getcaseidx( &scope, OpenLDAPaciscopes );
	if ( idx == -1 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid scope '%s'\n", scope.bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	scope = *OpenLDAPaciscopes[ idx ];

	/* rights */
	if ( acl_get_part( val, 2, '#', &rights ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing rights in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	if ( OpenLDAPaciNormalizeRights( &rights, &nrights, ctx )
		!= LDAP_SUCCESS )
	{
		return LDAP_INVALID_SYNTAX;
	}

	/* type */
	if ( acl_get_part( val, 3, '#', &type ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing type in '%s'\n", val->bv_val );
		rc = LDAP_INVALID_SYNTAX;
		goto cleanup;
	}
	idx = bv_getcaseidx( &type, OpenLDAPacitypes );
	if ( idx == -1 ) {
		struct berval	isgr;

		if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) {
		        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", type.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		idx = bv_getcaseidx( &isgr, OpenLDAPacitypes );
		if ( idx == -1 || idx >= LAST_OPTIONAL ) {
		        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", isgr.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}
	}
	ntype = *OpenLDAPacitypes[ idx ];

	/* subject */
	bv_get_tail( val, &type, &subject );

	if ( BER_BVISEMPTY( &subject ) || subject.bv_val[ 0 ] != '#' ) {
	        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing subject in '%s'\n", val->bv_val );
		rc = LDAP_INVALID_SYNTAX;
		goto cleanup;
	}

	subject.bv_val++;
	subject.bv_len--;

	if ( idx < LAST_DNVALUED ) {
		/* FIXME: pass DN syntax? */
		if ( normalize ) {
			rc = dnNormalize( 0, NULL, NULL,
				&subject, &nsubject, ctx );
		} else {
			rc = dnPretty( NULL, &subject, &nsubject, ctx );
		}

		if ( rc == LDAP_SUCCESS ) {
			freesubject = 1;

		} else {
	                Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid subject dn '%s'\n", subject.bv_val );
			goto cleanup;
		}

		if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ]
			|| OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] )
		{
			/* do {group|role}/oc/at check */
			struct berval	ocbv = BER_BVNULL,
					atbv = BER_BVNULL;

			ocbv.bv_val = ber_bvchr( &type, '/' );
			if ( ocbv.bv_val != NULL ) {
				ObjectClass		*oc = NULL;
				AttributeDescription	*ad = NULL;
				const char		*text = NULL;
				int			rc;
				struct berval		bv;

				bv.bv_len = ntype.bv_len;

				ocbv.bv_val++;
				ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val );

				atbv.bv_val = ber_bvchr( &ocbv, '/' );
				if ( atbv.bv_val != NULL ) {
					atbv.bv_val++;
					atbv.bv_len = type.bv_len
						- ( atbv.bv_val - type.bv_val );
					ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1;

					rc = slap_bv2ad( &atbv, &ad, &text );
					if ( rc != LDAP_SUCCESS ) {
	                                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown group attribute '%s'\n", atbv.bv_val );
						rc = LDAP_INVALID_SYNTAX;
						goto cleanup;
					}

					bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len;
				}

				oc = oc_bvfind( &ocbv );
				if ( oc == NULL ) {
                                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid group '%s'\n", ocbv.bv_val );
					rc = LDAP_INVALID_SYNTAX;
					goto cleanup;
				}

				bv.bv_len += STRLENOF( "/" ) + oc->soc_cname.bv_len;
				bv.bv_val = ber_memalloc_x( bv.bv_len + 1, ctx );

				ptr = bv.bv_val;
				ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len );
				ptr[ 0 ] = '/';
				ptr++;
				ptr = lutil_strncopy( ptr,
					oc->soc_cname.bv_val,
					oc->soc_cname.bv_len );
				if ( ad != NULL ) {
					ptr[ 0 ] = '/';
					ptr++;
					ptr = lutil_strncopy( ptr,
						ad->ad_cname.bv_val,
						ad->ad_cname.bv_len );
				}
				ptr[ 0 ] = '\0';

				ntype = bv;
				freetype = 1;
			}
		}

	} else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) {
		AttributeDescription	*ad = NULL;
		const char		*text = NULL;
		int			rc;

		rc = slap_bv2ad( &subject, &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown dn attribute '%s'\n", subject.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
			/* FIXME: allow nameAndOptionalUID? */
                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: wrong syntax for dn attribute '%s'\n", subject.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		nsubject = ad->ad_cname;

	} else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET ]
		|| OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET_REF ] )
	{
		/* NOTE: dunno how to normalize it... */
		nsubject = subject;
	}


	out->bv_len =
		oid.bv_len + STRLENOF( "#" )
		+ scope.bv_len + STRLENOF( "#" )
		+ nrights.bv_len + STRLENOF( "#" )
		+ ntype.bv_len + STRLENOF( "#" )
		+ nsubject.bv_len;

	out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx );
	ptr = lutil_strncopy( out->bv_val, oid.bv_val, oid.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, scope.bv_val, scope.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, nrights.bv_val, nrights.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	if ( !BER_BVISNULL( &nsubject ) ) {
		ptr = lutil_strncopy( ptr, nsubject.bv_val, nsubject.bv_len );
	}
	ptr[ 0 ] = '\0';

cleanup:;
	if ( freesubject ) {
		ber_memfree_x( nsubject.bv_val, ctx );
	}

	if ( freetype ) {
		ber_memfree_x( ntype.bv_val, ctx );
	}

	if ( !BER_BVISNULL( &nrights ) ) {
		ber_memfree_x( nrights.bv_val, ctx );
	}

	return rc;
}
Exemplo n.º 28
0
static int
authzid_response(
	Operation *op,
	SlapReply *rs )
{
	LDAPControl **ctrls;
	struct berval edn = BER_BVNULL;
	ber_len_t len = 0;
	int n = 0;

	assert( rs->sr_tag = LDAP_RES_BIND );

	if ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ) {
		authzid_conn_t *ac = op->o_controls[ authzid_cid ];
		if ( ac ) {
			authzid_conn_release( ac );
		} else {
			(void)authzid_conn_insert( op->o_conn, op->o_ctrlflag[ authzid_cid ] );
		}
		return SLAP_CB_CONTINUE;
	}

	(void)authzid_conn_remove( op->o_conn );

	if ( rs->sr_err != LDAP_SUCCESS ) {
		return SLAP_CB_CONTINUE;
	}

	if ( !BER_BVISEMPTY( &op->orb_edn ) ) {
		edn = op->orb_edn;

	} else if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
		edn = op->o_conn->c_dn;
	}

	if ( !BER_BVISEMPTY( &edn ) ) {
		ber_tag_t save_tag = op->o_tag;
		struct berval save_dn = op->o_dn;
		struct berval save_ndn = op->o_ndn;
		int rc;

		/* pretend it's an extop without data,
		 * so it is treated as a generic write
		 */
		op->o_tag = LDAP_REQ_EXTENDED;
		op->o_dn = edn;
		op->o_ndn = edn;
		rc = backend_check_restrictions( op, rs, NULL );
		op->o_tag = save_tag;
		op->o_dn = save_dn;
		op->o_ndn = save_ndn;
		if ( rc != LDAP_SUCCESS ) {
			rs->sr_err = LDAP_CONFIDENTIALITY_REQUIRED;
			return SLAP_CB_CONTINUE;
		}

		len = STRLENOF("dn:") + edn.bv_len;
	}

	/* save original controls in sc_private;
	 * will be restored by sc_cleanup
	 */
	if ( rs->sr_ctrls != NULL ) {
		op->o_callback->sc_private = rs->sr_ctrls;
		for ( ; rs->sr_ctrls[n] != NULL; n++ )
			;
	}

	ctrls = op->o_tmpalloc( sizeof( LDAPControl * )*( n + 2 ), op->o_tmpmemctx );
	n = 0;
	if ( rs->sr_ctrls ) {
		for ( ; rs->sr_ctrls[n] != NULL; n++ ) {
			ctrls[n] = rs->sr_ctrls[n];
		}
	}

	/* anonymous: "", otherwise "dn:<dn>" */
	ctrls[n] = op->o_tmpalloc( sizeof( LDAPControl ) + len + 1, op->o_tmpmemctx );
	ctrls[n]->ldctl_oid = LDAP_CONTROL_AUTHZID_RESPONSE;
	ctrls[n]->ldctl_iscritical = 0;
	ctrls[n]->ldctl_value.bv_len = len;
	ctrls[n]->ldctl_value.bv_val = (char *)&ctrls[n][1];
	if ( len ) {
		char *ptr;

		ptr = lutil_strcopy( ctrls[n]->ldctl_value.bv_val, "dn:" );
		ptr = lutil_strncopy( ptr, edn.bv_val, edn.bv_len );
	}
	ctrls[n]->ldctl_value.bv_val[len] = '\0';
	ctrls[n + 1] = NULL;

	rs->sr_ctrls = ctrls;

	return SLAP_CB_CONTINUE;
}