Ejemplo n.º 1
0
static int
nssov_db_open(
	BackendDB *be,
	ConfigReply *cr )
{
	slap_overinst *on = (slap_overinst *)be->bd_info;
	nssov_info *ni = on->on_bi.bi_private;
	nssov_mapinfo *mi;

	int i, sock;
	struct sockaddr_un addr;

	/* Set default bases */
	for (i=0; i<NM_NONE; i++) {
		if ( BER_BVISNULL( &ni->ni_maps[i].mi_base )) {
			ber_dupbv( &ni->ni_maps[i].mi_base, &be->be_nsuffix[0] );
		}
		if ( ni->ni_maps[i].mi_scope == LDAP_SCOPE_DEFAULT )
			ni->ni_maps[i].mi_scope = LDAP_SCOPE_SUBTREE;
	}
	/* validate attribute maps */
	mi = ni->ni_maps;
	for ( i=0; i<NM_NONE; i++,mi++) {
		const char *text;
		int j;
		for (j=0; !BER_BVISNULL(&mi->mi_attrkeys[j]); j++) {
			/* skip attrs we already validated */
			if ( mi->mi_attrs[j].an_desc ) continue;
			if ( slap_bv2ad( &mi->mi_attrs[j].an_name,
				&mi->mi_attrs[j].an_desc, &text )) {
				Debug(LDAP_DEBUG_ANY,"nssov: invalid attr \"%s\": %s\n",
					mi->mi_attrs[j].an_name.bv_val, text, 0 );
				return -1;
			}
		}
		BER_BVZERO(&mi->mi_attrs[j].an_name);
		mi->mi_attrs[j].an_desc = NULL;
	}

	/* Find host and authorizedService definitions */
	if ((ni->ni_pam_opts & NI_PAM_USERHOST) && !nssov_pam_host_ad)
	{
		const char *text;
		i = slap_str2ad("host", &nssov_pam_host_ad, &text);
		if (i != LDAP_SUCCESS) {
			Debug(LDAP_DEBUG_ANY,"nssov: host attr unknown: %s\n",
				text, 0, 0 );
			return -1;
		}
	}
	if ((ni->ni_pam_opts & (NI_PAM_USERSVC|NI_PAM_HOSTSVC)) &&
		!nssov_pam_svc_ad)
	{
		const char *text;
		i = slap_str2ad("authorizedService", &nssov_pam_svc_ad, &text);
		if (i != LDAP_SUCCESS) {
			Debug(LDAP_DEBUG_ANY,"nssov: authorizedService attr unknown: %s\n",
				text, 0, 0 );
			return -1;
		}
	}
	if ( slapMode & SLAP_SERVER_MODE ) {
		/* make sure /var/run/nslcd exists */
		if (mkdir(NSLCD_PATH, (mode_t) 0555)) {
			Debug(LDAP_DEBUG_TRACE,"nssov: mkdir(%s) failed (ignored): %s\n",
					NSLCD_PATH,strerror(errno),0);
		} else {
			Debug(LDAP_DEBUG_TRACE,"nssov: created %s\n",NSLCD_PATH,0,0);
		}

		/* create a socket */
		if ( (sock=socket(PF_UNIX,SOCK_STREAM,0))<0 )
		{
			Debug(LDAP_DEBUG_ANY,"nssov: cannot create socket: %s\n",strerror(errno),0,0);
			return -1;
		}
		/* remove existing named socket */
		if (unlink(NSLCD_SOCKET)<0)
		{
			Debug( LDAP_DEBUG_TRACE,"nssov: unlink() of "NSLCD_SOCKET" failed (ignored): %s\n",
							strerror(errno),0,0);
		}
		/* create socket address structure */
		memset(&addr,0,sizeof(struct sockaddr_un));
		addr.sun_family=AF_UNIX;
		strncpy(addr.sun_path,NSLCD_SOCKET,sizeof(addr.sun_path));
		addr.sun_path[sizeof(addr.sun_path)-1]='\0';
		/* bind to the named socket */
		if (bind(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_un)))
		{
			Debug( LDAP_DEBUG_ANY,"nssov: bind() to "NSLCD_SOCKET" failed: %s",
							strerror(errno),0,0);
			if (close(sock))
				Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0);
			return -1;
		}
		/* close the file descriptor on exit */
		if (fcntl(sock,F_SETFD,FD_CLOEXEC)<0)
		{
			Debug( LDAP_DEBUG_ANY,"nssov: fcntl(F_SETFL,O_NONBLOCK) failed: %s",strerror(errno),0,0);
			if (close(sock))
				Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0);
			return -1;
		}
		/* set permissions of socket so anybody can do requests */
		/* Note: we use chmod() here instead of fchmod() because
			 fchmod does not work on sockets
			 http://www.opengroup.org/onlinepubs/009695399/functions/fchmod.html
			 http://lkml.org/lkml/2005/5/16/11 */
		if (chmod(NSLCD_SOCKET,(mode_t)0666))
		{
			Debug( LDAP_DEBUG_ANY,"nssov: chmod(0666) failed: %s",strerror(errno),0,0);
			if (close(sock))
				Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0);
			return -1;
		}
		/* start listening for connections */
		if (listen(sock,SOMAXCONN)<0)
		{
			Debug( LDAP_DEBUG_ANY,"nssov: listen() failed: %s",strerror(errno),0,0);
			if (close(sock))
				Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0);
			return -1;
		}
		ni->ni_socket = sock;
		ni->ni_conn = connection_client_setup( sock, acceptconn, ni );
	}

	return 0;
}
Ejemplo n.º 2
0
int
ldap_back_search(
		Operation	*op,
		SlapReply	*rs )
{
	ldapinfo_t	*li = (ldapinfo_t *) op->o_bd->be_private;

	ldapconn_t	*lc = NULL;
	struct timeval	tv;
	time_t		stoptime = (time_t)(-1);
	LDAPMessage	*res,
			*e;
	int		rc = 0,
			msgid; 
	struct berval	match = BER_BVNULL,
			filter = BER_BVNULL;
	int		i, x;
	char		**attrs = NULL;
	int		freetext = 0, filter_undef = 0;
	int		do_retry = 1, dont_retry = 0;
	LDAPControl	**ctrls = NULL;
	char		**references = NULL;

	rs_assert_ready( rs );
	rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */

	if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
		return rs->sr_err;
	}

	/*
	 * FIXME: in case of values return filter, we might want
	 * to map attrs and maybe rewrite value
	 */

	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
		tv.tv_sec = op->ors_tlimit;
		tv.tv_usec = 0;
		stoptime = op->o_time + op->ors_tlimit;

	} else {
		LDAP_BACK_TV_SET( &tv );
	}

	i = 0;
	if ( op->ors_attrs ) {
		for ( ; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ )
			/* just count attrs */ ;
	}

	x = 0;
	if ( op->o_bd->be_extra_anlist ) {
		for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
			/* just count attrs */ ;
	}

	if ( i > 0 || x > 0 ) {
		int j = 0;

		attrs = op->o_tmpalloc( ( i + x + 1 )*sizeof( char * ),
			op->o_tmpmemctx );
		if ( attrs == NULL ) {
			rs->sr_err = LDAP_NO_MEMORY;
			rc = -1;
			goto finish;
		}

		if ( i > 0 ) {	
			for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++, j++ ) {
				attrs[ j ] = op->ors_attrs[i].an_name.bv_val;
			}
		}

		if ( x > 0 ) {
			for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++, j++ ) {
				if ( op->o_bd->be_extra_anlist[x].an_desc &&
					ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, op->ors_attrs ) )
				{
					continue;
				}

				attrs[ j ] = op->o_bd->be_extra_anlist[x].an_name.bv_val;
			}
		}

		attrs[ j ] = NULL;
	}

	ctrls = op->o_ctrls;
	rc = ldap_back_controls_add( op, rs, lc, &ctrls );
	if ( rc != LDAP_SUCCESS ) {
		goto finish;
	}

	/* deal with <draft-zeilenga-ldap-t-f> filters */
	filter = op->ors_filterstr;
retry:
	/* this goes after retry because ldap_back_munge_filter()
	 * optionally replaces RFC 4526 T-F filters (&) (|)
	 * if already computed, they will be re-installed
	 * by filter2bv_undef_x() later */
	if ( !LDAP_BACK_T_F( li ) ) {
		ldap_back_munge_filter( op, &filter );
	}

	rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val,
			op->ors_scope, filter.bv_val,
			attrs, op->ors_attrsonly, ctrls, NULL,
			tv.tv_sec ? &tv : NULL,
			op->ors_slimit, op->ors_deref, &msgid );

	ldap_pvt_thread_mutex_lock( &li->li_counter_mutex );
	ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_SEARCH ], 1 );
	ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex );

	if ( rs->sr_err != LDAP_SUCCESS ) {
		switch ( rs->sr_err ) {
		case LDAP_SERVER_DOWN:
			if ( do_retry ) {
				do_retry = 0;
				if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
					goto retry;
				}
			}

			if ( lc == NULL ) {
				/* reset by ldap_back_retry ... */
				rs->sr_err = slap_map_api2result( rs );

			} else {
				rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND );
			}
				
			goto finish;

		case LDAP_FILTER_ERROR:
			/* first try? */
			if ( !filter_undef &&
				strstr( filter.bv_val, "(?" ) &&
				!LDAP_BACK_NOUNDEFFILTER( li ) )
			{
				BER_BVZERO( &filter );
				filter2bv_undef_x( op, op->ors_filter, 1, &filter );
				filter_undef = 1;
				goto retry;
			}

			/* invalid filters return success with no data */
			rs->sr_err = LDAP_SUCCESS;
			rs->sr_text = NULL;
			goto finish;
		
		default:
			rs->sr_err = slap_map_api2result( rs );
			rs->sr_text = NULL;
			goto finish;
		}
	}

	/* if needed, initialize timeout */
	if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
		if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
			tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
			tv.tv_usec = 0;
		}
	}

	/* We pull apart the ber result, stuff it into a slapd entry, and
	 * let send_search_entry stuff it back into ber format. Slow & ugly,
	 * but this is necessary for version matching, and for ACL processing.
	 */

	for ( rc = -2; rc != -1; rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ONE, &tv, &res ) )
	{
		/* check for abandon */
		if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( lc ) ) {
			if ( rc > 0 ) {
				ldap_msgfree( res );
			}
			(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
			rc = SLAPD_ABANDON;
			goto finish;
		}

		if ( rc == 0 || rc == -2 ) {
			ldap_pvt_thread_yield();

			/* check timeout */
			if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
				if ( rc == 0 ) {
					(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
					rs->sr_text = "Operation timed out";
					rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
						LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
					goto finish;
				}

			} else {
				LDAP_BACK_TV_SET( &tv );
			}

			/* check time limit */
			if ( op->ors_tlimit != SLAP_NO_LIMIT
					&& slap_get_time() > stoptime )
			{
				(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
				rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
				goto finish;
			}
			continue;

		} else {
			/* only touch when activity actually took place... */
			if ( li->li_idle_timeout ) {
				lc->lc_time = op->o_time;
			}

			/* don't retry any more */
			dont_retry = 1;
		}


		if ( rc == LDAP_RES_SEARCH_ENTRY ) {
			Entry		ent = { 0 };
			struct berval	bdn = BER_BVNULL;

			do_retry = 0;

			e = ldap_first_entry( lc->lc_ld, res );
			rc = ldap_build_entry( op, e, &ent, &bdn );
			if ( rc == LDAP_SUCCESS ) {
				ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
				rs->sr_entry = &ent;
				rs->sr_attrs = op->ors_attrs;
				rs->sr_operational_attrs = NULL;
				rs->sr_flags = 0;
				rs->sr_err = LDAP_SUCCESS;
				rc = rs->sr_err = send_search_entry( op, rs );
				if ( rs->sr_ctrls ) {
					ldap_controls_free( rs->sr_ctrls );
					rs->sr_ctrls = NULL;
				}
				rs->sr_entry = NULL;
				rs->sr_flags = 0;
				if ( !BER_BVISNULL( &ent.e_name ) ) {
					assert( ent.e_name.bv_val != bdn.bv_val );
					op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );
					BER_BVZERO( &ent.e_name );
				}
				if ( !BER_BVISNULL( &ent.e_nname ) ) {
					op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx );
					BER_BVZERO( &ent.e_nname );
				}
				entry_clean( &ent );
			}
			ldap_msgfree( res );
			switch ( rc ) {
			case LDAP_SUCCESS:
			case LDAP_INSUFFICIENT_ACCESS:
				break;

			default:
				if ( rc == LDAP_UNAVAILABLE ) {
					rc = rs->sr_err = LDAP_OTHER;
				} else {
					(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
				}
				goto finish;
			}

		} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
			if ( LDAP_BACK_NOREFS( li ) ) {
				ldap_msgfree( res );
				continue;
			}

			do_retry = 0;
			rc = ldap_parse_reference( lc->lc_ld, res,
					&references, &rs->sr_ctrls, 1 );

			if ( rc != LDAP_SUCCESS ) {
				continue;
			}

			/* FIXME: there MUST be at least one */
			if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
				int		cnt;

				for ( cnt = 0; references[ cnt ]; cnt++ )
					/* NO OP */ ;

				/* FIXME: there MUST be at least one */
				rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
					op->o_tmpmemctx );

				for ( cnt = 0; references[ cnt ]; cnt++ ) {
					ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
				}
				BER_BVZERO( &rs->sr_ref[ cnt ] );

				/* ignore return value by now */
				RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) );
				rs->sr_entry = NULL;
				( void )send_search_reference( op, rs );

			} else {
				Debug( LDAP_DEBUG_ANY,
					"%s ldap_back_search: "
					"got SEARCH_REFERENCE "
					"with no referrals\n",
					op->o_log_prefix, 0, 0 );
			}

			/* cleanup */
			if ( references ) {
				ber_memvfree( (void **)references );
				op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
				rs->sr_ref = NULL;
				references = NULL;
			}

			if ( rs->sr_ctrls ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}

		} else if ( rc == LDAP_RES_INTERMEDIATE ) {
			/* FIXME: response controls
			 * are passed without checks */
			rc = ldap_parse_intermediate( lc->lc_ld,
				res,
				(char **)&rs->sr_rspoid,
				&rs->sr_rspdata,
				&rs->sr_ctrls,
				0 );
			if ( rc != LDAP_SUCCESS ) {
				continue;
			}

			slap_send_ldap_intermediate( op, rs );

			if ( rs->sr_rspoid != NULL ) {
				ber_memfree( (char *)rs->sr_rspoid );
				rs->sr_rspoid = NULL;
			}

			if ( rs->sr_rspdata != NULL ) {
				ber_bvfree( rs->sr_rspdata );
				rs->sr_rspdata = NULL;
			}

			if ( rs->sr_ctrls != NULL ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}

		} else {
			char		*err = NULL;

			rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
					&match.bv_val, &err,
					&references, &rs->sr_ctrls, 1 );
			if ( rc == LDAP_SUCCESS ) {
				if ( err ) {
					rs->sr_text = err;
					freetext = 1;
				}
			} else {
				rs->sr_err = rc;
			}
			rs->sr_err = slap_map_api2result( rs );

			/* RFC 4511: referrals can only appear
			 * if result code is LDAP_REFERRAL */
			if ( references 
				&& references[ 0 ]
				&& references[ 0 ][ 0 ] )
			{
				if ( rs->sr_err != LDAP_REFERRAL ) {
					Debug( LDAP_DEBUG_ANY,
						"%s ldap_back_search: "
						"got referrals with err=%d\n",
						op->o_log_prefix,
						rs->sr_err, 0 );

				} else {
					int	cnt;

					for ( cnt = 0; references[ cnt ]; cnt++ )
						/* NO OP */ ;
				
					rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
						op->o_tmpmemctx );

					for ( cnt = 0; references[ cnt ]; cnt++ ) {
						/* duplicating ...*/
						ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
					}
					BER_BVZERO( &rs->sr_ref[ cnt ] );
				}

			} else if ( rs->sr_err == LDAP_REFERRAL ) {
				Debug( LDAP_DEBUG_ANY,
					"%s ldap_back_search: "
					"got err=%d with null "
					"or empty referrals\n",
					op->o_log_prefix,
					rs->sr_err, 0 );

				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}

			if ( match.bv_val != NULL ) {
				match.bv_len = strlen( match.bv_val );
			}

			rc = 0;
			break;
		}

		/* if needed, restore timeout */
		if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
			if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
				tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
				tv.tv_usec = 0;
			}
		}
	}

 	if ( rc == -1 ) {
		if ( dont_retry == 0 ) {
			if ( do_retry ) {
				do_retry = 0;
				if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
					goto retry;
				}
			}

			rs->sr_err = LDAP_SERVER_DOWN;
			rs->sr_err = slap_map_api2result( rs );
			goto finish;

		} else if ( LDAP_BACK_ONERR_STOP( li ) ) {
			/* if onerr == STOP */
			rs->sr_err = LDAP_SERVER_DOWN;
			rs->sr_err = slap_map_api2result( rs );
			goto finish;
		}
	}

	/*
	 * Rewrite the matched portion of the search base, if required
	 */
	if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) {
		struct berval	pmatch;

		if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) != LDAP_SUCCESS ) {
			pmatch.bv_val = match.bv_val;
			match.bv_val = NULL;
		}
		rs->sr_matched = pmatch.bv_val;
		rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
	}

finish:;
	if ( !BER_BVISNULL( &match ) ) {
		ber_memfree( match.bv_val );
	}

	if ( rs->sr_v2ref ) {
		rs->sr_err = LDAP_REFERRAL;
	}

	if ( LDAP_BACK_QUARANTINE( li ) ) {
		ldap_back_quarantine( op, rs );
	}

	if ( filter.bv_val != op->ors_filterstr.bv_val ) {
		op->o_tmpfree( filter.bv_val, op->o_tmpmemctx );
	}

#if 0
	/* let send_ldap_result play cleanup handlers (ITS#4645) */
	if ( rc != SLAPD_ABANDON )
#endif
	{
		send_ldap_result( op, rs );
	}

	(void)ldap_back_controls_free( op, rs, &ctrls );

	if ( rs->sr_ctrls ) {
		ldap_controls_free( rs->sr_ctrls );
		rs->sr_ctrls = NULL;
	}

	if ( rs->sr_text ) {
		if ( freetext ) {
			ber_memfree( (char *)rs->sr_text );
		}
		rs->sr_text = NULL;
	}

	if ( rs->sr_ref ) {
		op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
		rs->sr_ref = NULL;
	}

	if ( references ) {
		ber_memvfree( (void **)references );
	}

	if ( attrs ) {
		op->o_tmpfree( attrs, op->o_tmpmemctx );
	}

	if ( lc != NULL ) {
		ldap_back_release_conn( li, lc );
	}

	if ( rs->sr_err == LDAP_UNAVAILABLE &&
		/* if we originally bound and wanted rebind-as-user, must drop
		 * the connection now because we just discarded the credentials.
		 * ITS#7464, #8142
		 */
		LDAP_BACK_SAVECRED( li ) && SLAP_IS_AUTHZ_BACKEND( op ) )
		rs->sr_err = SLAPD_DISCONNECT;
	return rs->sr_err;
}
Ejemplo n.º 3
0
Entry *
str2entry2( char *s, int checkvals, int *rc )
{
	int dummy;
	if (! rc)
		rc = &dummy;

	Entry		*e;
	struct berval	*type, *vals, *nvals;
	char 	*freeval;
	AttributeDescription *ad, *ad_prev;
	const char *text;
	char	*next;
	int		attr_cnt;
	int		i, lines;
	Attribute	ahead, *atail;

	/*
	 * LDIF is used as the string format.
	 * An entry looks like this:
	 *
	 *	dn: <dn>\n
	 *	[<attr>:[:] <value>\n]
	 *	[<tab><continuedvalue>\n]*
	 *	...
	 *
	 * If a double colon is used after a type, it means the
	 * following value is encoded as a base 64 string.  This
	 * happens if the value contains a non-printing character
	 * or newline.
	 */

	*rc = LDAP_OTHER;
	Debug( LDAP_DEBUG_TRACE, "=> str2entry: \"%s\"\n",
		s ? s : "NULL" );

	e = entry_alloc();

	if( e == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"<= str2entry NULL (entry allocation failed)\n" );
		*rc = LDAP_NO_MEMORY;
		return NULL;
	}

	/* initialize entry */
	e->e_id = NOID;

	/* dn + attributes */
	atail = &ahead;
	ahead.a_next = NULL;
	ad = NULL;
	ad_prev = NULL;
	attr_cnt = 0;
	next = s;

	lines = ldif_countlines( s );
	type = ch_calloc( 1, (lines+1)*3*sizeof(struct berval)+lines );
	vals = type+lines+1;
	nvals = vals+lines+1;
	freeval = (char *)(nvals+lines+1);
	i = -1;

	/* parse into individual values, record DN */
	while ( (s = ldif_getline( &next )) != NULL ) {
		int freev;
		if ( *s == '\n' || *s == '\0' ) {
			break;
		}
		i++;
		if (i >= lines) {
			Debug( LDAP_DEBUG_TRACE,
				"<= str2entry ran past end of entry\n" );
			*rc = LDAP_INVALID_SYNTAX;
			goto fail;
		}

		int err = ldif_parse_line2( s, type+i, vals+i, &freev );
		freeval[i] = freev;
		if ( err ) {
			Debug( LDAP_DEBUG_TRACE,
				"<= str2entry NULL (parse_line)\n" );
			*rc = LDAP_OTHER;
			continue;
		}

		if ( bvcasematch( &type[i], &dn_bv ) ) {
			if ( e->e_dn != NULL ) {
				Debug( LDAP_DEBUG_ANY, "str2entry: "
					"entry %ld has multiple DNs \"%s\" and \"%s\"\n",
					(long) e->e_id, e->e_dn, vals[i].bv_val );
				*rc = LDAP_INVALID_SYNTAX;
				goto fail;
			}

			*rc = dnPrettyNormal( NULL, &vals[i], &e->e_name, &e->e_nname, NULL );
			if( *rc != LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_ANY, "str2entry: "
					"entry %ld has invalid DN \"%s\"\n",
					(long) e->e_id, vals[i].bv_val );
				goto fail;
			}
			if ( freeval[i] ) free( vals[i].bv_val );
			vals[i].bv_val = NULL;
			i--;
			continue;
		}
	}
	lines = i+1;

	/* check to make sure there was a dn: line */
	if ( BER_BVISNULL( &e->e_name )) {
		Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n",
			(long) e->e_id );
		*rc = LDAP_INVALID_SYNTAX;
		goto fail;
	}

	/* Make sure all attributes with multiple values are contiguous */
	if ( checkvals ) {
		int j, k;
		struct berval bv;
		int fv;

		for (i=0; i<lines; i++) {
			for ( j=i+1; j<lines; j++ ) {
				if ( bvcasematch( type+i, type+j )) {
					/* out of order, move intervening attributes down */
					if ( j != i+1 ) {
						bv = vals[j];
						fv = freeval[j];
						for ( k=j; k>i; k-- ) {
							type[k] = type[k-1];
							vals[k] = vals[k-1];
							freeval[k] = freeval[k-1];
						}
						k++;
						type[k] = type[i];
						vals[k] = bv;
						freeval[k] = fv;
					}
					i++;
				}
			}
		}
	}

	if ( lines > 0 ) {
		for ( i=0; i<=lines; i++ ) {
			ad_prev = ad;
			if ( !ad || ( i<lines && !bvcasematch( type+i, &ad->ad_cname ))) {
				ad = NULL;
				*rc = slap_bv2ad( type+i, &ad, &text );

				if( *rc != LDAP_SUCCESS ) {
					int wtool = ( slapMode & (SLAP_TOOL_MODE|SLAP_TOOL_READONLY) ) == SLAP_TOOL_MODE;
					Debug( wtool ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE,
						"<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text );
					if( wtool ) {
						goto fail;
					}

					*rc = slap_bv2undef_ad( type+i, &ad, &text, 0 );
					if( *rc != LDAP_SUCCESS ) {
						Debug( LDAP_DEBUG_ANY,
							"<= str2entry: slap_str2undef_ad(%s): %s\n",
								type[i].bv_val, text );
						goto fail;
					}
				}

				/* require ';binary' when appropriate (ITS#5071) */
				if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) {
					Debug( LDAP_DEBUG_ANY,
						"str2entry: attributeType %s #%d: "
						"needs ';binary' transfer as per syntax %s\n",
						ad->ad_cname.bv_val, 0,
						ad->ad_type->sat_syntax->ssyn_oid );
					*rc = LDAP_INVALID_SYNTAX;
					goto fail;
				}
			}

			if (( ad_prev && ad != ad_prev ) || ( i == lines )) {
				int j, k;
				atail->a_next = attr_alloc( NULL );
				atail = atail->a_next;
				atail->a_flags = 0;
				atail->a_numvals = attr_cnt;
				atail->a_desc = ad_prev;
				atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval));
				if( ad_prev->ad_type->sat_equality &&
					ad_prev->ad_type->sat_equality->smr_normalize )
					atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval));
				else
					atail->a_nvals = NULL;
				k = i - attr_cnt;
				for ( j=0; j<attr_cnt; j++ ) {
					if ( freeval[k] )
						atail->a_vals[j] = vals[k];
					else
						ber_dupbv( atail->a_vals+j, &vals[k] );
					vals[k].bv_val = NULL;
					if ( atail->a_nvals ) {
						atail->a_nvals[j] = nvals[k];
						nvals[k].bv_val = NULL;
					}
					k++;
				}
				BER_BVZERO( &atail->a_vals[j] );
				if ( atail->a_nvals ) {
					BER_BVZERO( &atail->a_nvals[j] );
				} else {
					atail->a_nvals = atail->a_vals;
				}
				attr_cnt = 0;
				/* FIXME: we only need this when migrating from an unsorted DB */
				if ( atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
					*rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL );
					if ( *rc == LDAP_SUCCESS ) {
						atail->a_flags |= SLAP_ATTR_SORTED_VALS;
					} else if ( *rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
						Debug( LDAP_DEBUG_ANY,
							"str2entry: attributeType %s value #%d provided more than once\n",
							atail->a_desc->ad_cname.bv_val, j );
						goto fail;
					}
				}
				if ( i == lines ) break;
			}

			if ( BER_BVISNULL( &vals[i] ) ) {
				Debug( LDAP_DEBUG_ANY,
					"str2entry: attributeType %s #%d: "
					"no value\n",
					ad->ad_cname.bv_val, attr_cnt );
				*rc = LDAP_INVALID_SYNTAX;
				goto fail;
			}

			if ( ad->ad_type->sat_equality &&
				ad->ad_type->sat_equality->smr_normalize )
			{
				*rc = ordered_value_normalize(
					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
					ad,
					ad->ad_type->sat_equality,
					&vals[i], &nvals[i], NULL );

				if ( *rc ) {
					Debug( LDAP_DEBUG_ANY,
						"<= str2entry NULL (smr_normalize %s='%s' %d)\n",
						ad->ad_cname.bv_val, vals[i].bv_val, *rc );
					goto fail;
				}
			}

			attr_cnt++;
		}
	}

	free( type );
	atail->a_next = NULL;
	e->e_attrs = ahead.a_next;

	*rc = LDAP_SUCCESS;
	Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n",
		e->e_dn, (unsigned long) e );
	return e;

fail:
	for ( i=0; i<lines; i++ ) {
		if ( freeval[i] ) free( vals[i].bv_val );
		free( nvals[i].bv_val );
	}
	free( type );
	entry_free( e );
	return NULL;
}
Ejemplo n.º 4
0
int
load_extop2(
	const struct berval *ext_oid,
	slap_mask_t ext_flags,
	SLAP_EXTOP_MAIN_FN *ext_main,
	unsigned flags )
{
	struct berval		oidm = BER_BVNULL;
	struct extop_list	*ext;
	int			insertme = 0;

	if ( !ext_main ) {
		return -1; 
	}

	if ( ext_oid == NULL || BER_BVISNULL( ext_oid ) ||
		BER_BVISEMPTY( ext_oid ) )
	{
		return -1; 
	}

	if ( numericoidValidate( NULL, (struct berval *)ext_oid ) !=
		LDAP_SUCCESS )
	{
		oidm.bv_val = oidm_find( ext_oid->bv_val );
		if ( oidm.bv_val == NULL ) {
			return -1;
		}
		oidm.bv_len = strlen( oidm.bv_val );
		ext_oid = &oidm;
	}

	for ( ext = supp_ext_list; ext; ext = ext->next ) {
		if ( bvmatch( ext_oid, &ext->oid ) ) {
			if ( flags == 1 ) {
				break;
			}
			return -1;
		}
	}

	if ( flags == 0 || ext == NULL ) {
		ext = ch_calloc( 1, sizeof(struct extop_list) + ext_oid->bv_len + 1 );
		if ( ext == NULL ) {
			return(-1);
		}

		ext->oid.bv_val = (char *)(ext + 1);
		AC_MEMCPY( ext->oid.bv_val, ext_oid->bv_val, ext_oid->bv_len );
		ext->oid.bv_len = ext_oid->bv_len;
		ext->oid.bv_val[ext->oid.bv_len] = '\0';

		insertme = 1;
	}

	ext->flags = ext_flags;
	ext->ext_main = ext_main;

	if ( insertme ) {
		ext->next = supp_ext_list;
		supp_ext_list = ext;
	}

	return(0);
}
Ejemplo n.º 5
0
int
ndb_back_modrdn( Operation *op, SlapReply *rs )
{
	struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
	AttributeDescription *children = slap_schema.si_ad_children;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	struct berval	new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
	Entry		e = {0};
	Entry		e2 = {0};
	char textbuf[SLAP_TEXT_BUFLEN];
	size_t textlen = sizeof textbuf;

	struct berval	*np_dn = NULL;			/* newSuperior dn */
	struct berval	*np_ndn = NULL;			/* newSuperior ndn */

	int		manageDSAit = get_manageDSAit( op );
	int		num_retries = 0;

	NdbArgs NA, NA2;
	NdbRdns rdns, rdn2;
	struct berval matched;

	LDAPControl **preread_ctrl = NULL;
	LDAPControl **postread_ctrl = NULL;
	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
	int num_ctrls = 0;

	int	rc;

	Debug( LDAP_DEBUG_ARGS, "==>" LDAP_XSTRING(ndb_back_modrdn) "(%s,%s,%s)\n",
		op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
		op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );

	ctrls[num_ctrls] = NULL;

	slap_mods_opattrs( op, &op->orr_modlist, 1 );

	e.e_name = op->o_req_dn;
	e.e_nname = op->o_req_ndn;

	/* Get our NDB handle */
	rs->sr_err = ndb_thread_handle( op, &NA.ndb );
	rdns.nr_num = 0;
	NA.rdns = &rdns;
	NA.e = &e;
	NA2.ndb = NA.ndb;
	NA2.e = &e2;
	NA2.rdns = &rdn2;

	if( 0 ) {
retry:	/* transaction retry */
		NA.txn->close();
		NA.txn = NULL;
		if ( e.e_attrs ) {
			attrs_free( e.e_attrs );
			e.e_attrs = NULL;
		}
		Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(ndb_back_modrdn)
				": retrying...\n", 0, 0, 0 );
		if ( op->o_abandon ) {
			rs->sr_err = SLAPD_ABANDON;
			goto return_results;
		}
		if ( NA2.ocs ) {
			ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx );
		}
		if ( NA.ocs ) {
			ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
		}
		ndb_trans_backoff( ++num_retries );
	}
	NA.ocs = NULL;
	NA2.ocs = NULL;

	/* begin transaction */
	NA.txn = NA.ndb->startTransaction();
	rs->sr_text = NULL;
	if( !NA.txn ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(ndb_back_modrdn) ": startTransaction failed: %s (%d)\n",
			NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	NA2.txn = NA.txn;

	/* get entry */
	rs->sr_err = ndb_entry_get_info( op, &NA, 1, &matched );
	switch( rs->sr_err ) {
	case 0:
		break;
	case LDAP_NO_SUCH_OBJECT:
		Debug( LDAP_DEBUG_ARGS,
			"<=- ndb_back_modrdn: no such object %s\n",
			op->o_req_dn.bv_val, 0, 0 );
		rs->sr_matched = matched.bv_val;
		if ( NA.ocs )
			ndb_check_referral( op, rs, &NA );
		goto return_results;
#if 0
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto retry;
#endif
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	/* acquire and lock entry */
	rs->sr_err = ndb_entry_get_data( op, &NA, 1 );
	if ( rs->sr_err )
		goto return_results;

	if ( !manageDSAit && is_entry_glue( &e )) {
		rs->sr_err = LDAP_NO_SUCH_OBJECT;
		goto return_results;
	}

	if ( get_assert( op ) &&
		( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE ))
	{
		rs->sr_err = LDAP_ASSERTION_FAILED;
		goto return_results;
	}

	/* check write on old entry */
	rs->sr_err = access_allowed( op, &e, entry, NULL, ACL_WRITE, NULL );
	if ( ! rs->sr_err ) {
		Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
			0, 0 );
		rs->sr_text = "no write access to old entry";
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		goto return_results;
	}

	/* Can't do it if we have kids */
	rs->sr_err = ndb_has_children( &NA, &rc );
	if ( rs->sr_err ) {
		Debug(LDAP_DEBUG_ARGS,
			"<=- " LDAP_XSTRING(ndb_back_modrdn)
			": has_children failed: %s (%d)\n",
			NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	if ( rc == LDAP_COMPARE_TRUE ) {
		Debug(LDAP_DEBUG_ARGS,
			"<=- " LDAP_XSTRING(ndb_back_modrdn)
			": non-leaf %s\n",
			op->o_req_dn.bv_val, 0, 0);
		rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
		rs->sr_text = "subtree rename not supported";
		goto return_results;
	}

	if (!manageDSAit && is_entry_referral( &e ) ) {
		/* entry is a referral, don't allow modrdn */
		rs->sr_ref = get_entry_referrals( op, &e );

		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn)
			": entry %s is referral\n", e.e_dn, 0, 0 );

		rs->sr_err = LDAP_REFERRAL,
		rs->sr_matched = op->o_req_dn.bv_val;
		rs->sr_flags = REP_REF_MUSTBEFREED;
		goto return_results;
	}

	if ( be_issuffix( op->o_bd, &e.e_nname ) ) {
		/* There can only be one suffix entry */
		rs->sr_err = LDAP_NAMING_VIOLATION;
		rs->sr_text = "cannot rename suffix entry";
		goto return_results;
	} else {
		dnParent( &e.e_nname, &e2.e_nname );
		dnParent( &e.e_name, &e2.e_name );
	}

	/* check parent for "children" acl */
	rs->sr_err = access_allowed( op, &e2,
		children, NULL,
		op->oq_modrdn.rs_newSup == NULL ?
			ACL_WRITE : ACL_WDEL,
		NULL );

	if ( ! rs->sr_err ) {
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
			0, 0 );
		rs->sr_text = "no write access to old parent's children";
		goto return_results;
	}

	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(ndb_back_modrdn) ": wr to children "
		"of entry %s OK\n", e2.e_name.bv_val, 0, 0 );

	if ( op->oq_modrdn.rs_newSup != NULL ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(ndb_back_modrdn)
			": new parent \"%s\" requested...\n",
			op->oq_modrdn.rs_newSup->bv_val, 0, 0 );

		/*  newSuperior == oldParent? */
		if( dn_match( &e2.e_nname, op->oq_modrdn.rs_nnewSup ) ) {
			Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
				"new parent \"%s\" same as the old parent \"%s\"\n",
				op->oq_modrdn.rs_newSup->bv_val, e2.e_name.bv_val, 0 );
			op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
		}
	}

	if ( op->oq_modrdn.rs_newSup != NULL ) {
		if ( op->oq_modrdn.rs_newSup->bv_len ) {
			rdn2.nr_num = 0;
			np_dn = op->oq_modrdn.rs_newSup;
			np_ndn = op->oq_modrdn.rs_nnewSup;

			/* newSuperior == oldParent? - checked above */
			/* newSuperior == entry being moved?, if so ==> ERROR */
			if ( dnIsSuffix( np_ndn, &e.e_nname )) {
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
				rs->sr_text = "new superior not found";
				goto return_results;
			}
			/* Get Entry with dn=newSuperior. Does newSuperior exist? */

			e2.e_name = *np_dn;
			e2.e_nname = *np_ndn;
			rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL );
			switch( rs->sr_err ) {
			case 0:
				break;
			case LDAP_NO_SUCH_OBJECT:
				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(ndb_back_modrdn)
					": newSup(ndn=%s) not here!\n",
					np_ndn->bv_val, 0, 0);
				rs->sr_text = "new superior not found";
				goto return_results;
#if 0
			case DB_LOCK_DEADLOCK:
			case DB_LOCK_NOTGRANTED:
				goto retry;
#endif
			case LDAP_BUSY:
				rs->sr_text = "ldap server busy";
				goto return_results;
			default:
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error";
				goto return_results;
			}
			if ( NA2.ocs ) {
				Attribute a;
				int i;

				for ( i=0; !BER_BVISNULL( &NA2.ocs[i] ); i++);
				a.a_numvals = i;
				a.a_desc = slap_schema.si_ad_objectClass;
				a.a_vals = NA2.ocs;
				a.a_nvals = NA2.ocs;
				a.a_next = NULL;
				e2.e_attrs = &a;

				if ( is_entry_alias( &e2 )) {
					/* parent is an alias, don't allow move */
					Debug( LDAP_DEBUG_TRACE,
						LDAP_XSTRING(ndb_back_modrdn)
						": entry is alias\n",
						0, 0, 0 );
					rs->sr_text = "new superior is an alias";
					rs->sr_err = LDAP_ALIAS_PROBLEM;
					goto return_results;
				}

				if ( is_entry_referral( &e2 ) ) {
					/* parent is a referral, don't allow move */
					Debug( LDAP_DEBUG_TRACE,
						LDAP_XSTRING(ndb_back_modrdn)
						": entry is referral\n",
						0, 0, 0 );
					rs->sr_text = "new superior is a referral";
					rs->sr_err = LDAP_OTHER;
					goto return_results;
				}
			}
		}

		/* check newSuperior for "children" acl */
		rs->sr_err = access_allowed( op, &e2, children,
			NULL, ACL_WADD, NULL );
		if( ! rs->sr_err ) {
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(ndb_back_modrdn)
				": no wr to newSup children\n",
				0, 0, 0 );
			rs->sr_text = "no write access to new superior's children";
			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
			goto return_results;
		}

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(ndb_back_modrdn)
			": wr to new parent OK id=%ld\n",
			(long) e2.e_id, 0, 0 );
	}

	/* Build target dn and make sure target entry doesn't exist already. */
	if (!new_dn.bv_val) {
		build_new_dn( &new_dn, &e2.e_name, &op->oq_modrdn.rs_newrdn, NULL );
	}

	if (!new_ndn.bv_val) {
		build_new_dn( &new_ndn, &e2.e_nname, &op->oq_modrdn.rs_nnewrdn, NULL );
	}

	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": new ndn=%s\n",
		new_ndn.bv_val, 0, 0 );

	/* Allow rename to same DN */
	if ( !bvmatch ( &new_ndn, &e.e_nname )) {
		rdn2.nr_num = 0;
		e2.e_name = new_dn;
		e2.e_nname = new_ndn;
		NA2.ocs = &matched;
		rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL );
		NA2.ocs = NULL;
		switch( rs->sr_err ) {
#if 0
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
#endif
		case LDAP_NO_SUCH_OBJECT:
			break;
		case 0:
			rs->sr_err = LDAP_ALREADY_EXISTS;
			goto return_results;
		default:
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
			goto return_results;
		}
	}

	assert( op->orr_modlist != NULL );

	if( op->o_preread ) {
		if( preread_ctrl == NULL ) {
			preread_ctrl = &ctrls[num_ctrls++];
			ctrls[num_ctrls] = NULL;
		}
		if( slap_read_controls( op, rs, &e,
			&slap_pre_read_bv, preread_ctrl ) )
		{
			Debug( LDAP_DEBUG_TRACE,
				"<=- " LDAP_XSTRING(ndb_back_modrdn)
				": pre-read failed!\n", 0, 0, 0 );
			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
				/* FIXME: is it correct to abort
				 * operation if control fails? */
				goto return_results;
			}
		}
	}

	/* delete old DN */
	rs->sr_err = ndb_entry_del_info( op->o_bd, &NA );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(ndb_back_modrdn)
			": dn2id del failed: %s (%d)\n",
			NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
#if 0
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
#endif
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "DN index delete fail";
		goto return_results;
	}

	/* copy entry fields */
	e2.e_attrs = e.e_attrs;
	e2.e_id = e.e_id;

	/* add new DN */
	rs->sr_err = ndb_entry_put_info( op->o_bd, &NA2, 0 );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(ndb_back_modrdn)
			": dn2id add failed: %s (%d)\n",
			NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
#if 0
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
#endif
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "DN index add failed";
		goto return_results;
	}

	/* modify entry */
	rs->sr_err = ndb_modify_internal( op, &NA2,
		&rs->sr_text, textbuf, textlen );
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(ndb_back_modrdn)
			": modify failed: %s (%d)\n",
			NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
#if 0
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
#endif
		goto return_results;
	}

	e.e_attrs = e2.e_attrs;

	if( op->o_postread ) {
		if( postread_ctrl == NULL ) {
			postread_ctrl = &ctrls[num_ctrls++];
			ctrls[num_ctrls] = NULL;
		}
		if( slap_read_controls( op, rs, &e2,
			&slap_post_read_bv, postread_ctrl ) )
		{
			Debug( LDAP_DEBUG_TRACE,
				"<=- " LDAP_XSTRING(ndb_back_modrdn)
				": post-read failed!\n", 0, 0, 0 );
			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
				/* FIXME: is it correct to abort
				 * operation if control fails? */
				goto return_results;
			}
		}
	}

	if( op->o_noop ) {
		if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback,
			NdbOperation::AbortOnError, 1 )) != 0 ) {
			rs->sr_text = "txn_abort (no-op) failed";
		} else {
			rs->sr_err = LDAP_X_NO_OPERATION;
		}
	} else {
		if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit,
			NdbOperation::AbortOnError, 1 )) != 0 ) {
			rs->sr_text = "txn_commit failed";
		} else {
			rs->sr_err = LDAP_SUCCESS;
		}
	}

	if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(ndb_back_modrdn) ": txn_%s failed: %s (%d)\n",
			op->o_noop ? "abort (no-op)" : "commit",
			NA.txn->getNdbError().message, NA.txn->getNdbError().code );
		rs->sr_err = LDAP_OTHER;
		goto return_results;
	}
	NA.txn->close();
	NA.txn = NULL;

	Debug(LDAP_DEBUG_TRACE,
		LDAP_XSTRING(ndb_back_modrdn)
		": rdn modified%s id=%08lx dn=\"%s\"\n",
		op->o_noop ? " (no-op)" : "",
		e.e_id, op->o_req_dn.bv_val );

	rs->sr_err = LDAP_SUCCESS;
	rs->sr_text = NULL;
	if( num_ctrls ) rs->sr_ctrls = ctrls;

return_results:
	if ( NA2.ocs ) {
		ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx );
		NA2.ocs = NULL;
	}

	if ( NA.ocs ) {
		ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
		NA.ocs = NULL;
	}

	if ( e.e_attrs ) {
		attrs_free( e.e_attrs );
		e.e_attrs = NULL;
	}

	if( NA.txn != NULL ) {
		NA.txn->execute( Rollback );
		NA.txn->close();
	}

	send_ldap_result( op, rs );
	slap_graduate_commit_csn( op );

	if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
	if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );

	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
	}
	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
	}

	rs->sr_text = NULL;
	return rs->sr_err;
}
Ejemplo n.º 6
0
/*
 * Do basic attribute type checking and syntax validation.
 */
int slap_mods_check(
	Operation *op,
	Modifications *ml,
	const char **text,
	char *textbuf,
	size_t textlen,
	void *ctx )
{
	int rc;

	for( ; ml != NULL; ml = ml->sml_next ) {
		AttributeDescription *ad = NULL;

		/* convert to attribute description */
		if ( ml->sml_desc == NULL ) {
			rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text );
			if( rc != LDAP_SUCCESS ) {
				if ( get_no_schema_check( op )) {
					rc = slap_bv2undef_ad( &ml->sml_type, &ml->sml_desc,
						text, 0 );
				}
			}
			if( rc != LDAP_SUCCESS ) {
				snprintf( textbuf, textlen, "%s: %s",
					ml->sml_type.bv_val, *text );
				*text = textbuf;
				return rc;
			}
		}

		ad = ml->sml_desc;

		if( slap_syntax_is_binary( ad->ad_type->sat_syntax )
			&& !slap_ad_is_binary( ad ))
		{
			/* attribute requires binary transfer */
			snprintf( textbuf, textlen,
				"%s: requires ;binary transfer",
				ml->sml_type.bv_val );
			*text = textbuf;
			return LDAP_UNDEFINED_TYPE;
		}

		if( !slap_syntax_is_binary( ad->ad_type->sat_syntax )
			&& slap_ad_is_binary( ad ))
		{
			/* attribute does not require binary transfer */
			snprintf( textbuf, textlen,
				"%s: disallows ;binary transfer",
				ml->sml_type.bv_val );
			*text = textbuf;
			return LDAP_UNDEFINED_TYPE;
		}

		if( slap_ad_is_tag_range( ad )) {
			/* attribute requires binary transfer */
			snprintf( textbuf, textlen,
				"%s: inappropriate use of tag range option",
				ml->sml_type.bv_val );
			*text = textbuf;
			return LDAP_UNDEFINED_TYPE;
		}

#if 0
		if ( is_at_obsolete( ad->ad_type ) &&
			(( ml->sml_op != LDAP_MOD_REPLACE &&
				ml->sml_op != LDAP_MOD_DELETE ) ||
					ml->sml_values != NULL ))
		{
			/*
			 * attribute is obsolete,
			 * only allow replace/delete with no values
			 */
			snprintf( textbuf, textlen,
				"%s: attribute is obsolete",
				ml->sml_type.bv_val );
			*text = textbuf;
			return LDAP_CONSTRAINT_VIOLATION;
		}
#endif

		if ( ml->sml_op == LDAP_MOD_INCREMENT &&
#ifdef SLAPD_REAL_SYNTAX
			!is_at_syntax( ad->ad_type, SLAPD_REAL_SYNTAX ) &&
#endif
			!is_at_syntax( ad->ad_type, SLAPD_INTEGER_SYNTAX ) )
		{
			/*
			 * attribute values must be INTEGER or REAL
			 */
			snprintf( textbuf, textlen,
				"%s: attribute syntax inappropriate for increment",
				ml->sml_type.bv_val );
			*text = textbuf;
			return LDAP_CONSTRAINT_VIOLATION;
		}

		/*
		 * check values
		 */
		if( ml->sml_values != NULL ) {
			ber_len_t nvals;
			slap_syntax_validate_func *validate =
				ad->ad_type->sat_syntax->ssyn_validate;
			slap_syntax_transform_func *pretty =
				ad->ad_type->sat_syntax->ssyn_pretty;
 
			if( !pretty && !validate ) {
				*text = "no validator for syntax";
				snprintf( textbuf, textlen,
					"%s: no validator for syntax %s",
					ml->sml_type.bv_val,
					ad->ad_type->sat_syntax->ssyn_oid );
				*text = textbuf;
				return LDAP_INVALID_SYNTAX;
			}

			/*
			 * check that each value is valid per syntax
			 *	and pretty if appropriate
			 */
			for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) {
				struct berval pval;

				if ( pretty ) {
					rc = ordered_value_pretty( ad,
						&ml->sml_values[nvals], &pval, ctx );
				} else {
					rc = ordered_value_validate( ad,
						&ml->sml_values[nvals], ml->sml_op );
				}

				if( rc != 0 ) {
					snprintf( textbuf, textlen,
						"%s: value #%ld invalid per syntax",
						ml->sml_type.bv_val, (long) nvals );
					*text = textbuf;
					return LDAP_INVALID_SYNTAX;
				}

				if( pretty ) {
					ber_memfree_x( ml->sml_values[nvals].bv_val, ctx );
					ml->sml_values[nvals] = pval;
				}
			}
			ml->sml_values[nvals].bv_len = 0;
			ml->sml_numvals = nvals;

			/*
			 * a rough single value check... an additional check is needed
			 * to catch add of single value to existing single valued attribute
			 */
			if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE)
				&& nvals > 1 && is_at_single_value( ad->ad_type ))
			{
				snprintf( textbuf, textlen,
					"%s: multiple values provided",
					ml->sml_type.bv_val );
				*text = textbuf;
				return LDAP_CONSTRAINT_VIOLATION;
			}

			/* if the type has a normalizer, generate the
			 * normalized values. otherwise leave them NULL.
			 *
			 * this is different from the rule for attributes
			 * in an entry - in an attribute list, the normalized
			 * value is set equal to the non-normalized value
			 * when there is no normalizer.
			 */
			if( nvals && ad->ad_type->sat_equality &&
				ad->ad_type->sat_equality->smr_normalize )
			{
				ml->sml_nvalues = ber_memalloc_x(
					(nvals+1)*sizeof(struct berval), ctx );

				for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) {
					rc = ordered_value_normalize(
						SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
						ad,
						ad->ad_type->sat_equality,
						&ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx );
					if ( rc ) {
						Debug( LDAP_DEBUG_ANY,
							"<= str2entry NULL (ssyn_normalize %d)\n",
							rc, 0, 0 );
						snprintf( textbuf, textlen,
							"%s: value #%ld normalization failed",
							ml->sml_type.bv_val, (long) nvals );
						*text = textbuf;
						BER_BVZERO( &ml->sml_nvalues[nvals] );
						return rc;
					}
				}

				BER_BVZERO( &ml->sml_nvalues[nvals] );
			}

			/* check for duplicates, but ignore Deletes.
			 */
			if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) {
				int i;
				rc = slap_sort_vals( ml, text, &i, ctx );
				if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
					/* value exists already */
					snprintf( textbuf, textlen,
						"%s: value #%d provided more than once",
						ml->sml_desc->ad_cname.bv_val, i );
					*text = textbuf;
				}
				if ( rc )
					return rc;
			}
		} else {
			ml->sml_numvals = 0;
		}
	}

	return LDAP_SUCCESS;
}
Ejemplo n.º 7
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 )
		{
			slap_bv2undef_ad( &op->ors_attrs[i].an_name,
				&op->ors_attrs[i].an_desc, &dummy,
				SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
		};
	}

	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;
}
Ejemplo n.º 8
0
static int vlv_parseCtrl(
	Operation		*op,
	SlapReply		*rs,
	LDAPControl		*ctrl )
{
	BerElementBuffer	berbuf;
	BerElement			*ber;
	ber_tag_t		tag;
	ber_len_t		len;
	vlv_ctrl	*vc, vc2;

	rs->sr_err = LDAP_PROTOCOL_ERROR;
	rs->sr_text = NULL;

	if ( op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ) {
		rs->sr_text = "vlv control specified multiple times";
	} else if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
		rs->sr_text = "vlv control value is absent";
	} else if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
		rs->sr_text = "vlv control value is empty";
	}
	if ( rs->sr_text != NULL )
		return rs->sr_err;

	op->o_ctrlflag[vlv_cid] = ctrl->ldctl_iscritical ?
		SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL;

	ber = (BerElement *)&berbuf;
	ber_init2( ber, &ctrl->ldctl_value, 0 );

	rs->sr_err = LDAP_PROTOCOL_ERROR;

	tag = ber_scanf( ber, "{ii", &vc2.vc_before, &vc2.vc_after );
	if ( tag == LBER_ERROR ) {
		return rs->sr_err;
	}

	tag = ber_peek_tag( ber, &len );
	if ( tag == LDAP_VLVBYINDEX_IDENTIFIER ) {
		tag = ber_scanf( ber, "{ii}", &vc2.vc_offset, &vc2.vc_count );
		if ( tag == LBER_ERROR )
			return rs->sr_err;
		BER_BVZERO( &vc2.vc_value );
	} else if ( tag == LDAP_VLVBYVALUE_IDENTIFIER ) {
		tag = ber_scanf( ber, "m", &vc2.vc_value );
		if ( tag == LBER_ERROR || BER_BVISNULL( &vc2.vc_value ))
			return rs->sr_err;
	} else {
		return rs->sr_err;
	}
	tag = ber_peek_tag( ber, &len );
	if ( tag == LDAP_VLVCONTEXT_IDENTIFIER ) {
		struct berval bv;
		tag = ber_scanf( ber, "m", &bv );
		if ( tag == LBER_ERROR || bv.bv_len != sizeof(vc2.vc_context))
			return rs->sr_err;
		memcpy( &vc2.vc_context, bv.bv_val, bv.bv_len );
	} else {
		vc2.vc_context = 0;
	}

	vc = op->o_tmpalloc( sizeof(vlv_ctrl), op->o_tmpmemctx );
	*vc = vc2;
	op->o_controls[vlv_cid] = vc;
	rs->sr_err = LDAP_SUCCESS;

	return rs->sr_err;
}
Ejemplo n.º 9
0
static void send_list(
	Operation		*op,
	SlapReply		*rs,
	sort_op			*so)
{
	Avlnode	*cur_node, *tmp_node;
	vlv_ctrl *vc = op->o_controls[vlv_cid];
	int i, j, dir, rc;
	BackendDB *be;
	Entry *e;
	LDAPControl *ctrls[2];

	rs->sr_attrs = op->ors_attrs;

	/* FIXME: it may be better to just flatten the tree into
	 * an array before doing all of this...
	 */

	/* Are we just counting an offset? */
	if ( BER_BVISNULL( &vc->vc_value )) {
		if ( vc->vc_offset == vc->vc_count ) {
			/* wants the last entry in the list */
			cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
			so->so_vlv_target = so->so_nentries;
		} else if ( vc->vc_offset == 1 ) {
			/* wants the first entry in the list */
			cur_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
			so->so_vlv_target = 1;
		} else {
			int target;
			/* Just iterate to the right spot */
			if ( vc->vc_count && vc->vc_count != so->so_nentries ) {
				if ( vc->vc_offset > vc->vc_count )
					goto range_err;
				target = so->so_nentries * vc->vc_offset / vc->vc_count;
			} else {
				if ( vc->vc_offset > so->so_nentries ) {
range_err:
					so->so_vlv_rc = LDAP_VLV_RANGE_ERROR;
					pack_vlv_response_control( op, rs, so, ctrls );
					ctrls[1] = NULL;
					slap_add_ctrls( op, rs, ctrls );
					rs->sr_err = LDAP_VLV_ERROR;
					return;
				}
				target = vc->vc_offset;
			}
			so->so_vlv_target = target;
			/* Start at left and go right, or start at right and go left? */
			if ( target < so->so_nentries / 2 ) {
				cur_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
				dir = TAVL_DIR_RIGHT;
			} else {
				cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
				dir = TAVL_DIR_LEFT;
				target = so->so_nentries - target + 1;
			}
			for ( i=1; i<target; i++ )
				cur_node = tavl_next( cur_node, dir );
		}
	} else {
	/* we're looking for a specific value */
		sort_ctrl *sc = so->so_ctrl;
		MatchingRule *mr = sc->sc_keys[0].sk_ordering;
		sort_node *sn;
		struct berval bv;

		if ( mr->smr_normalize ) {
			rc = mr->smr_normalize( SLAP_MR_VALUE_OF_SYNTAX,
				mr->smr_syntax, mr, &vc->vc_value, &bv, op->o_tmpmemctx );
			if ( rc ) {
				so->so_vlv_rc = LDAP_INAPPROPRIATE_MATCHING;
				pack_vlv_response_control( op, rs, so, ctrls );
				ctrls[1] = NULL;
				slap_add_ctrls( op, rs, ctrls );
				rs->sr_err = LDAP_VLV_ERROR;
				return;
			}
		} else {
			bv = vc->vc_value;
		}

		sn = op->o_tmpalloc( sizeof(sort_node) +
			sc->sc_nkeys * sizeof(struct berval), op->o_tmpmemctx );
		sn->sn_vals = (struct berval *)(sn+1);
		sn->sn_conn = op->o_conn->c_conn_idx;
		sn->sn_session = find_session_by_so( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, so );
		sn->sn_vals[0] = bv;
		for (i=1; i<sc->sc_nkeys; i++) {
			BER_BVZERO( &sn->sn_vals[i] );
		}
		cur_node = tavl_find3( so->so_tree, sn, node_cmp, &j );
		/* didn't find >= match */
		if ( j > 0 ) {
			if ( cur_node )
				cur_node = tavl_next( cur_node, TAVL_DIR_RIGHT );
		}
		op->o_tmpfree( sn, op->o_tmpmemctx );

		if ( !cur_node ) {
			so->so_vlv_target = so->so_nentries + 1;
		} else {
			sort_node *sn = so->so_tree->avl_data;
			/* start from the left or the right side? */
			mr->smr_match( &i, 0, mr->smr_syntax, mr, &bv, &sn->sn_vals[0] );
			if ( i > 0 ) {
				tmp_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
				dir = TAVL_DIR_LEFT;
			} else {
				tmp_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
				dir = TAVL_DIR_RIGHT;
			}
			for (i=0; tmp_node != cur_node;
				tmp_node = tavl_next( tmp_node, dir ), i++);
			so->so_vlv_target = (dir == TAVL_DIR_RIGHT) ? i+1 : so->so_nentries - i;
		}
		if ( bv.bv_val != vc->vc_value.bv_val )
			op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
	}
	if ( !cur_node ) {
		i = 1;
		cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
	} else {
		i = 0;
	}
	for ( ; i<vc->vc_before; i++ ) {
		tmp_node = tavl_next( cur_node, TAVL_DIR_LEFT );
		if ( !tmp_node ) break;
		cur_node = tmp_node;
	}
	j = i + vc->vc_after + 1;
	be = op->o_bd;
	for ( i=0; i<j; i++ ) {
		sort_node *sn = cur_node->avl_data;

		if ( slapd_shutdown ) break;

		op->o_bd = select_backend( &sn->sn_dn, 0 );
		e = NULL;
		rc = be_entry_get_rw( op, &sn->sn_dn, NULL, NULL, 0, &e );

		if ( e && rc == LDAP_SUCCESS ) {
			rs->sr_entry = e;
			rs->sr_flags = REP_ENTRY_MUSTRELEASE;
			rs->sr_err = send_search_entry( op, rs );
			if ( rs->sr_err == LDAP_UNAVAILABLE )
				break;
		}
		cur_node = tavl_next( cur_node, TAVL_DIR_RIGHT );
		if ( !cur_node ) break;
	}
	so->so_vlv_rc = LDAP_SUCCESS;

	op->o_bd = be;
}
Ejemplo n.º 10
0
int
backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
{
	Operation		*op = bsi->bsi_op;
	backsql_info		*bi = (backsql_info *)op->o_bd->be_private;
	int			i;
	int			rc;

	Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );

	assert( bsi->bsi_e != NULL );

	memset( bsi->bsi_e, 0, sizeof( Entry ) );

	if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
		(void)entry_dup2( bsi->bsi_e, bi->sql_baseObject );
		goto done;
	}

	bsi->bsi_e->e_attrs = NULL;
	bsi->bsi_e->e_private = NULL;

	if ( eid->eid_oc == NULL ) {
		eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
			eid->eid_oc_id );
		if ( eid->eid_oc == NULL ) {
			Debug( LDAP_DEBUG_TRACE,
				"backsql_id2entry(): unable to fetch objectClass with id=" BACKSQL_IDNUMFMT " for entry id=" BACKSQL_IDFMT " dn=\"%s\"\n",
				eid->eid_oc_id, BACKSQL_IDARG(eid->eid_id),
				eid->eid_dn.bv_val );
			return LDAP_OTHER;
		}
	}
	bsi->bsi_oc = eid->eid_oc;
	bsi->bsi_c_eid = eid;

	ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx );
	ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx );

#ifndef BACKSQL_ARBITRARY_KEY	
	/* FIXME: unused */
	bsi->bsi_e->e_id = eid->eid_id;
#endif /* ! BACKSQL_ARBITRARY_KEY */
 
	rc = attr_merge_normalize_one( bsi->bsi_e,
			slap_schema.si_ad_objectClass,
			&bsi->bsi_oc->bom_oc->soc_cname,
			bsi->bsi_op->o_tmpmemctx );
	if ( rc != LDAP_SUCCESS ) {
		backsql_entry_clean( op, bsi->bsi_e );
		return rc;
	}

	if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
	{
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"retrieving all attributes\n", 0, 0, 0 );
		avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
				bsi, 0, AVL_INORDER );

	} else {
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"custom attribute list\n", 0, 0, 0 );
		for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) {
			backsql_at_map_rec	**vat;
			AttributeName		*an = &bsi->bsi_attrs[ i ];
			int			j;

			/* if one of the attributes listed here is
			 * a subtype of another, it must be ignored,
			 * because subtypes are already dealt with
			 * by backsql_supad2at()
			 */
			for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) {
				/* skip self */
				if ( j == i ) {
					continue;
				}

				/* skip subtypes */
				if ( is_at_subtype( an->an_desc->ad_type,
							bsi->bsi_attrs[ j ].an_desc->ad_type ) )
				{
					goto next;
				}
			}

			rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
			if ( rc != 0 || vat == NULL ) {
				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
						"attribute \"%s\" is not defined "
						"for objectlass \"%s\"\n",
						an->an_name.bv_val, 
						BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
				continue;
			}

			for ( j = 0; vat[j]; j++ ) {
    				backsql_get_attr_vals( vat[j], bsi );
			}

			ch_free( vat );

next:;
		}
	}

	if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
		Attribute	*a_entryUUID,
				**ap;

		a_entryUUID = backsql_operational_entryUUID( bi, eid );
		if ( a_entryUUID != NULL ) {
			for ( ap = &bsi->bsi_e->e_attrs; 
					*ap; 
					ap = &(*ap)->a_next );

			*ap = a_entryUUID;
		}
	}

	if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
			|| an_find( bsi->bsi_attrs, slap_bv_all_operational_attrs )
			|| an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
	{
		ObjectClass	*soc = NULL;

		if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
			Attribute	*a;
			const char	*text = NULL;
			char		textbuf[ 1024 ];
			size_t		textlen = sizeof( textbuf );
			struct berval	bv[ 2 ],
					*nvals;
			int		rc = LDAP_SUCCESS;

			a = attr_find( bsi->bsi_e->e_attrs,
					slap_schema.si_ad_objectClass );
			if ( a != NULL ) {
				nvals = a->a_nvals;

			} else {
				bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
				BER_BVZERO( &bv[ 1 ] );
				nvals = bv;
			}

			rc = structural_class( nvals, &soc, NULL, 
					&text, textbuf, textlen, op->o_tmpmemctx );
			if ( rc != LDAP_SUCCESS ) {
      				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
					"structural_class() failed %d (%s)\n",
					bsi->bsi_e->e_name.bv_val,
					rc, text ? text : "" );
				backsql_entry_clean( op, bsi->bsi_e );
				return rc;
			}

			if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
				if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
      					Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
						"computed structuralObjectClass %s "
						"does not match objectClass %s associated "
						"to entry\n",
						bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
						bsi->bsi_oc->bom_oc->soc_cname.bv_val );
					backsql_entry_clean( op, bsi->bsi_e );
					return rc;
				}

      				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
					"computed structuralObjectClass %s "
					"is subclass of objectClass %s associated "
					"to entry\n",
					bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
					bsi->bsi_oc->bom_oc->soc_cname.bv_val );
			}

		} else {
			soc = bsi->bsi_oc->bom_oc;
		}

		rc = attr_merge_normalize_one( bsi->bsi_e,
				slap_schema.si_ad_structuralObjectClass,
				&soc->soc_cname,
				bsi->bsi_op->o_tmpmemctx );
		if ( rc != LDAP_SUCCESS ) {
			backsql_entry_clean( op, bsi->bsi_e );
			return rc;
		}
	}

done:;
	Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );

	return LDAP_SUCCESS;
}
Ejemplo n.º 11
0
int
ldap_back_modify(
		Operation	*op,
		SlapReply	*rs )
{
	ldapinfo_t		*li = (ldapinfo_t *)op->o_bd->be_private;

	ldapconn_t		*lc = NULL;
	LDAPMod			**modv = NULL,
				*mods = NULL;
	Modifications		*ml;
	int			i, j, rc;
	ber_int_t		msgid;
	int			isupdate;
	ldap_back_send_t	retrying = LDAP_BACK_RETRYING;
	LDAPControl		**ctrls = NULL;

	if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
		return rs->sr_err;
	}

	for ( i = 0, ml = op->orm_modlist; ml; i++, ml = ml->sml_next )
		/* just count mods */ ;

	modv = (LDAPMod **)ch_malloc( ( i + 1 )*sizeof( LDAPMod * )
			+ i*sizeof( LDAPMod ) );
	if ( modv == NULL ) {
		rc = LDAP_NO_MEMORY;
		goto cleanup;
	}
	mods = (LDAPMod *)&modv[ i + 1 ];

	isupdate = be_shadow_update( op );
	for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) {
		if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
		{
			continue;
		}

		modv[ i ] = &mods[ i ];
		mods[ i ].mod_op = ( ml->sml_op | LDAP_MOD_BVALUES );
		mods[ i ].mod_type = ml->sml_desc->ad_cname.bv_val;

		if ( ml->sml_values != NULL ) {
			if ( ml->sml_values == NULL ) {	
				continue;
			}

			for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ )
				/* just count mods */ ;
			mods[ i ].mod_bvalues =
				(struct berval **)ch_malloc( ( j + 1 )*sizeof( struct berval * ) );
			for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ )
			{
				mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ];
			}
			mods[ i ].mod_bvalues[ j ] = NULL;

		} else {
			mods[ i ].mod_bvalues = NULL;
		}

		i++;
	}
	modv[ i ] = 0;

retry:;
	ctrls = op->o_ctrls;
	rc = ldap_back_controls_add( op, rs, lc, &ctrls );
	if ( rc != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		rc = -1;
		goto cleanup;
	}

	rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_dn.bv_val, modv,
			ctrls, NULL, &msgid );
	rc = ldap_back_op_result( lc, op, rs, msgid,
		li->li_timeout[ SLAP_OP_MODIFY ],
		( LDAP_BACK_SENDRESULT | retrying ) );
	if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
		retrying &= ~LDAP_BACK_RETRYING;
		if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
			/* if the identity changed, there might be need to re-authz */
			(void)ldap_back_controls_free( op, rs, &ctrls );
			goto retry;
		}
	}

	ldap_pvt_thread_mutex_lock( &li->li_counter_mutex );
	ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_MODIFY ], 1 );
	ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex );

cleanup:;
	(void)ldap_back_controls_free( op, rs, &ctrls );

	for ( i = 0; modv[ i ]; i++ ) {
		ch_free( modv[ i ]->mod_bvalues );
	}
	ch_free( modv );

	if ( lc != NULL ) {
		ldap_back_release_conn( li, lc );
	}

	return rc;
}
Ejemplo n.º 12
0
static int
backsql_get_attr_vals( void *v_at, void *v_bsi )
{
	backsql_at_map_rec	*at = v_at;
	backsql_srch_info	*bsi = v_bsi;
	backsql_info		*bi;
	RETCODE			rc;
	SQLHSTMT		sth = SQL_NULL_HSTMT;
	BACKSQL_ROW_NTS		row;
	unsigned long		i,
				k = 0,
				oldcount = 0,
				res = 0;
#ifdef BACKSQL_COUNTQUERY
	unsigned 		count,
				j,
				append = 0;
	SQLLEN			countsize = sizeof( count );
	Attribute		*attr = NULL;

	slap_mr_normalize_func		*normfunc = NULL;
#endif /* BACKSQL_COUNTQUERY */
#ifdef BACKSQL_PRETTY_VALIDATE
	slap_syntax_validate_func	*validate = NULL;
	slap_syntax_transform_func	*pretty = NULL;
#endif /* BACKSQL_PRETTY_VALIDATE */

	assert( at != NULL );
	assert( bsi != NULL );
	Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
		"oc=\"%s\" attr=\"%s\" keyval=" BACKSQL_IDFMT "\n",
		BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 
		BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval) );

	bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;

#ifdef BACKSQL_PRETTY_VALIDATE
	validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate;
	pretty =  at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty;

	if ( validate == NULL && pretty == NULL ) {
		return 1;
	}
#endif /* BACKSQL_PRETTY_VALIDATE */

#ifdef BACKSQL_COUNTQUERY
	if ( at->bam_true_ad->ad_type->sat_equality ) {
		normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize;
	}

	/* Count how many rows will be returned. This avoids memory 
	 * fragmentation that can result from loading the values in 
	 * one by one and using realloc() 
	 */
	rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_countquery, 0 );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error preparing count query: %s\n",
			at->bam_countquery, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
		return 1;
	}

	rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
			&bsi->bsi_c_eid->eid_keyval );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error binding key value parameter\n", 0, 0, 0 );
		SQLFreeStmt( sth, SQL_DROP );
		return 1;
	}

	rc = SQLExecute( sth );
	if ( ! BACKSQL_SUCCESS( rc ) ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error executing attribute count query '%s'\n",
			at->bam_countquery, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
		SQLFreeStmt( sth, SQL_DROP );
		return 1;
	}

	SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_LONG,
			(SQLPOINTER)&count,
			(SQLINTEGER)sizeof( count ),
			&countsize );

	rc = SQLFetch( sth );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error fetch results of count query: %s\n",
			at->bam_countquery, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
		SQLFreeStmt( sth, SQL_DROP );
		return 1;
	}

	Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
		"number of values in query: %u\n", count, 0, 0 );
	SQLFreeStmt( sth, SQL_DROP );
	if ( count == 0 ) {
		return 1;
	}

	attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad );
	if ( attr != NULL ) {
		BerVarray	tmp;

		if ( attr->a_vals != NULL ) {
			oldcount = attr->a_numvals;
		}

		tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
		if ( tmp == NULL ) {
			return 1;
		}
		attr->a_vals = tmp;
		memset( &attr->a_vals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );

		if ( normfunc ) {
			tmp = ch_realloc( attr->a_nvals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
			if ( tmp == NULL ) {
				return 1;
			}
			attr->a_nvals = tmp;
			memset( &attr->a_nvals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );

		} else {
			attr->a_nvals = attr->a_vals;
		}
		attr->a_numvals += count;

	} else {
		append = 1;

		/* Make space for the array of values */
		attr = attr_alloc( at->bam_true_ad );
		attr->a_numvals = count;
		attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
		if ( attr->a_vals == NULL ) {
			Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 );
			ch_free( attr );
			return 1;
		}
		if ( normfunc ) {
			attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) );
			if ( attr->a_nvals == NULL ) {
				ch_free( attr->a_vals );
				ch_free( attr );
				return 1;

			}

		} else {
			attr->a_nvals = attr->a_vals;
		}
	}
#endif /* BACKSQL_COUNTQUERY */

	rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error preparing query: %s\n", at->bam_query, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
#ifdef BACKSQL_COUNTQUERY
		if ( append ) {
			attr_free( attr );
		}
#endif /* BACKSQL_COUNTQUERY */
		return 1;
	}

	rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
			&bsi->bsi_c_eid->eid_keyval );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error binding key value parameter\n", 0, 0, 0 );
#ifdef BACKSQL_COUNTQUERY
		if ( append ) {
			attr_free( attr );
		}
#endif /* BACKSQL_COUNTQUERY */
		return 1;
	}

#ifdef BACKSQL_TRACE
	Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
		"query=\"%s\" keyval=" BACKSQL_IDFMT "\n", at->bam_query,
		BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval), 0 );
#endif /* BACKSQL_TRACE */

	rc = SQLExecute( sth );
	if ( ! BACKSQL_SUCCESS( rc ) ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error executing attribute query \"%s\"\n",
			at->bam_query, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
		SQLFreeStmt( sth, SQL_DROP );
#ifdef BACKSQL_COUNTQUERY
		if ( append ) {
			attr_free( attr );
		}
#endif /* BACKSQL_COUNTQUERY */
		return 1;
	}

	backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx );
#ifdef BACKSQL_COUNTQUERY
	j = oldcount;
#endif /* BACKSQL_COUNTQUERY */
	for ( rc = SQLFetch( sth ), k = 0;
			BACKSQL_SUCCESS( rc );
			rc = SQLFetch( sth ), k++ )
	{
		for ( i = 0; i < (unsigned long)row.ncols; i++ ) {

			if ( row.value_len[ i ] > 0 ) {
				struct berval		bv;
				int			retval;
#ifdef BACKSQL_TRACE
				AttributeDescription	*ad = NULL;
				const char		*text;

				retval = slap_bv2ad( &row.col_names[ i ], &ad, &text );
				if ( retval != LDAP_SUCCESS ) {
					Debug( LDAP_DEBUG_ANY,
						"==>backsql_get_attr_vals(\"%s\"): "
						"unable to find AttributeDescription %s "
						"in schema (%d)\n",
						bsi->bsi_e->e_name.bv_val,
						row.col_names[ i ].bv_val, retval );
					res = 1;
					goto done;
				}

				if ( ad != at->bam_ad ) {
					Debug( LDAP_DEBUG_ANY,
						"==>backsql_get_attr_vals(\"%s\"): "
						"column name %s differs from "
						"AttributeDescription %s\n",
						bsi->bsi_e->e_name.bv_val,
						ad->ad_cname.bv_val,
						at->bam_ad->ad_cname.bv_val );
					res = 1;
					goto done;
				}
#endif /* BACKSQL_TRACE */

				/* ITS#3386, ITS#3113 - 20070308
				 * If a binary is fetched?
				 * must use the actual size read
				 * from the database.
				 */
				if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
#ifdef BACKSQL_TRACE
					Debug( LDAP_DEBUG_ANY,
						"==>backsql_get_attr_vals(\"%s\"): "
						"column name %s: data is binary; "
						"using database size %ld\n",
						bsi->bsi_e->e_name.bv_val,
						ad->ad_cname.bv_val,
						row.value_len[ i ] );
#endif /* BACKSQL_TRACE */
					bv.bv_val = row.cols[ i ];
					bv.bv_len = row.value_len[ i ];

				} else {
					ber_str2bv( row.cols[ i ], 0, 0, &bv );
				}

#ifdef BACKSQL_PRETTY_VALIDATE
				if ( pretty ) {
					struct berval	pbv;

					retval = pretty( at->bam_true_ad->ad_type->sat_syntax,
						&bv, &pbv, bsi->bsi_op->o_tmpmemctx );
					bv = pbv;

				} else {
					retval = validate( at->bam_true_ad->ad_type->sat_syntax,
						&bv );
				}

				if ( retval != LDAP_SUCCESS ) {
					char	buf[ SLAP_TEXT_BUFLEN ];

					/* FIXME: we're ignoring invalid values,
					 * but we're accepting the attributes;
					 * should we fail at all? */
					snprintf( buf, sizeof( buf ),
							"unable to %s value #%lu "
							"of AttributeDescription %s",
							pretty ? "prettify" : "validate",
							k - oldcount,
							at->bam_ad->ad_cname.bv_val );
					Debug( LDAP_DEBUG_TRACE,
						"==>backsql_get_attr_vals(\"%s\"): "
						"%s (%d)\n",
						bsi->bsi_e->e_name.bv_val, buf, retval );
					continue;
				}
#endif /* BACKSQL_PRETTY_VALIDATE */

#ifndef BACKSQL_COUNTQUERY
				(void)backsql_entry_addattr( bsi->bsi_e, 
						at->bam_true_ad, &bv,
						bsi->bsi_op->o_tmpmemctx );

#else /* BACKSQL_COUNTQUERY */
				if ( normfunc ) {
					struct berval	nbv;

					retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
						at->bam_true_ad->ad_type->sat_syntax,
						at->bam_true_ad->ad_type->sat_equality,
						&bv, &nbv,
						bsi->bsi_op->o_tmpmemctx );

					if ( retval != LDAP_SUCCESS ) {
						char	buf[ SLAP_TEXT_BUFLEN ];

						/* FIXME: we're ignoring invalid values,
						 * but we're accepting the attributes;
						 * should we fail at all? */
						snprintf( buf, sizeof( buf ),
							"unable to normalize value #%lu "
							"of AttributeDescription %s",
							k - oldcount,
							at->bam_ad->ad_cname.bv_val );
						Debug( LDAP_DEBUG_TRACE,
							"==>backsql_get_attr_vals(\"%s\"): "
							"%s (%d)\n",
							bsi->bsi_e->e_name.bv_val, buf, retval );

#ifdef BACKSQL_PRETTY_VALIDATE
						if ( pretty ) {
							bsi->bsi_op->o_tmpfree( bv.bv_val,
									bsi->bsi_op->o_tmpmemctx );
						}
#endif /* BACKSQL_PRETTY_VALIDATE */

						continue;
					}
					ber_dupbv( &attr->a_nvals[ j ], &nbv );
					bsi->bsi_op->o_tmpfree( nbv.bv_val,
							bsi->bsi_op->o_tmpmemctx );
				}

				ber_dupbv( &attr->a_vals[ j ], &bv );

				assert( j < oldcount + count );
				j++;
#endif /* BACKSQL_COUNTQUERY */

#ifdef BACKSQL_PRETTY_VALIDATE
				if ( pretty ) {
					bsi->bsi_op->o_tmpfree( bv.bv_val,
							bsi->bsi_op->o_tmpmemctx );
				}
#endif /* BACKSQL_PRETTY_VALIDATE */

#ifdef BACKSQL_TRACE
				Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
					(int)row.col_prec[ i ], 0, 0 );

			} else {
      				Debug( LDAP_DEBUG_TRACE, "NULL value "
					"in this row for attribute \"%s\"\n",
					row.col_names[ i ].bv_val, 0, 0 );
#endif /* BACKSQL_TRACE */
			}
		}
	}

#ifdef BACKSQL_COUNTQUERY
	if ( BER_BVISNULL( &attr->a_vals[ 0 ] ) ) {
		/* don't leave around attributes with no values */
		attr_free( attr );

	} else if ( append ) {
		Attribute	**ap;

		for ( ap = &bsi->bsi_e->e_attrs; (*ap) != NULL; ap = &(*ap)->a_next )
			/* goto last */ ;
		*ap =  attr;
	}
#endif /* BACKSQL_COUNTQUERY */

	SQLFreeStmt( sth, SQL_DROP );
	Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );

	if ( at->bam_next ) {
		res = backsql_get_attr_vals( at->bam_next, v_bsi );
	} else {
		res = 1;
	}

#ifdef BACKSQL_TRACE
done:;
#endif /* BACKSQL_TRACE */
	backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx );

	return res;
}
Ejemplo n.º 13
0
/*
 * NOTE: the dn must be normalized
 */
int
backsql_dn2id(
	Operation		*op,
	SlapReply		*rs,
	SQLHDBC			dbh,
	struct berval		*ndn,
	backsql_entryID		*id,
	int			matched,
	int			muck )
{
	backsql_info		*bi = op->o_bd->be_private;
	SQLHSTMT		sth = SQL_NULL_HSTMT; 
	BACKSQL_ROW_NTS		row = { 0 };
	RETCODE 		rc;
	int			res;
	struct berval		realndn = BER_BVNULL;

	/* TimesTen */
	char			upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
	struct berval		tbbDN;
	int			i, j;

	/*
	 * NOTE: id can be NULL; in this case, the function
	 * simply checks whether the DN can be successfully 
	 * turned into an ID, returning LDAP_SUCCESS for
	 * positive cases, or the most appropriate error
	 */

	Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n", 
			ndn->bv_val, id == NULL ? " (no ID expected)" : "",
			matched ? " matched expected" : "" );

	if ( id ) {
		/* NOTE: trap inconsistencies */
		assert( BER_BVISNULL( &id->eid_ndn ) );
	}

	if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
		Debug( LDAP_DEBUG_TRACE, 
			"   backsql_dn2id(\"%s\"): DN length=%ld "
			"exceeds max DN length %d:\n",
			ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
		return LDAP_OTHER;
	}

	/* return baseObject if available and matches */
	/* FIXME: if ndn is already mucked, we cannot check this */
	if ( bi->sql_baseObject != NULL &&
			dn_match( ndn, &bi->sql_baseObject->e_nname ) )
	{
		if ( id != NULL ) {
#ifdef BACKSQL_ARBITRARY_KEY
			ber_dupbv_x( &id->eid_id, &backsql_baseObject_bv,
					op->o_tmpmemctx );
			ber_dupbv_x( &id->eid_keyval, &backsql_baseObject_bv,
					op->o_tmpmemctx );
#else /* ! BACKSQL_ARBITRARY_KEY */
			id->eid_id = BACKSQL_BASEOBJECT_ID;
			id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
#endif /* ! BACKSQL_ARBITRARY_KEY */
			id->eid_oc_id = BACKSQL_BASEOBJECT_OC;

			ber_dupbv_x( &id->eid_ndn, &bi->sql_baseObject->e_nname,
					op->o_tmpmemctx );
			ber_dupbv_x( &id->eid_dn, &bi->sql_baseObject->e_name,
					op->o_tmpmemctx );

			id->eid_next = NULL;
		}

		return LDAP_SUCCESS;
	}
	
	/* begin TimesTen */
	assert( bi->sql_id_query != NULL );
	Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): id_query \"%s\"\n",
			ndn->bv_val, bi->sql_id_query, 0 );
 	rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, 
			"   backsql_dn2id(\"%s\"): "
			"error preparing SQL:\n   %s", 
			ndn->bv_val, bi->sql_id_query, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
		res = LDAP_OTHER;
		goto done;
	}

	realndn = *ndn;
	if ( muck ) {
		if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
				"backsql_api_dn2odbc(\"%s\") failed\n", 
				ndn->bv_val, realndn.bv_val, 0 );
			res = LDAP_OTHER;
			goto done;
		}
	}

	if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
		/*
		 * Prepare an upper cased, byte reversed version 
		 * that can be searched using indexes
		 */

		for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
		{
			upperdn[ i ] = realndn.bv_val[ j ];
		}
		upperdn[ i ] = '\0';
		ldap_pvt_str2upper( upperdn );

		Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
				"upperdn=\"%s\"\n",
				ndn->bv_val, upperdn, 0 );
		ber_str2bv( upperdn, 0, 0, &tbbDN );

	} else {
		if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
			AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
			ldap_pvt_str2upper( upperdn );
			Debug( LDAP_DEBUG_TRACE,
				"   backsql_dn2id(\"%s\"): "
				"upperdn=\"%s\"\n",
				ndn->bv_val, upperdn, 0 );
			ber_str2bv( upperdn, 0, 0, &tbbDN );

		} else {
			tbbDN = realndn;
		}
	}

	rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
	if ( rc != SQL_SUCCESS) {
		/* end TimesTen */ 
		Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
			"error binding dn=\"%s\" parameter:\n", 
			ndn->bv_val, tbbDN.bv_val, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
		res = LDAP_OTHER;
		goto done;
	}

	rc = SQLExecute( sth );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
			"error executing query (\"%s\", \"%s\"):\n", 
			ndn->bv_val, bi->sql_id_query, tbbDN.bv_val );
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
		res = LDAP_OTHER;
		goto done;
	}

	backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
	rc = SQLFetch( sth );
	if ( BACKSQL_SUCCESS( rc ) ) {
		char	buf[ SLAP_TEXT_BUFLEN ];

#ifdef LDAP_DEBUG
		snprintf( buf, sizeof(buf),
			"id=%s keyval=%s oc_id=%s dn=%s",
			row.cols[ 0 ], row.cols[ 1 ],
			row.cols[ 2 ], row.cols[ 3 ] );
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_dn2id(\"%s\"): %s\n",
			ndn->bv_val, buf, 0 );
#endif /* LDAP_DEBUG */

		res = LDAP_SUCCESS;
		if ( id != NULL ) {
			struct berval	dn;

			id->eid_next = NULL;

#ifdef BACKSQL_ARBITRARY_KEY
			ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id,
					op->o_tmpmemctx );
			ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval,
					op->o_tmpmemctx );
#else /* ! BACKSQL_ARBITRARY_KEY */
			if ( BACKSQL_STR2ID( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) {
				res = LDAP_OTHER;
				goto done;
			}
			if ( BACKSQL_STR2ID( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) {
				res = LDAP_OTHER;
				goto done;
			}
#endif /* ! BACKSQL_ARBITRARY_KEY */
			if ( BACKSQL_STR2ID( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) {
				res = LDAP_OTHER;
				goto done;
			}

			ber_str2bv( row.cols[ 3 ], 0, 0, &dn );

			if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
				res = LDAP_OTHER;
				goto done;
			}
			
			res = dnPrettyNormal( NULL, &dn,
					&id->eid_dn, &id->eid_ndn,
					op->o_tmpmemctx );
			if ( res != LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_dn2id(\"%s\"): "
					"dnPrettyNormal failed (%d: %s)\n",
					realndn.bv_val, res,
					ldap_err2string( res ) );

				/* cleanup... */
				(void)backsql_free_entryID( id, 0, op->o_tmpmemctx );
			}

			if ( dn.bv_val != row.cols[ 3 ] ) {
				free( dn.bv_val );
			}
		}

	} else {
		res = LDAP_NO_SUCH_OBJECT;
		if ( matched ) {
			struct berval	pdn = *ndn;

			/*
			 * Look for matched
			 */
			rs->sr_matched = NULL;
			while ( !be_issuffix( op->o_bd, &pdn ) ) {
				char		*matchedDN = NULL;
	
				dnParent( &pdn, &pdn );
	
				/*
				 * Empty DN ("") defaults to LDAP_SUCCESS
				 */
				rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 );
				switch ( rs->sr_err ) {
				case LDAP_NO_SUCH_OBJECT:
					/* try another one */
					break;
					
				case LDAP_SUCCESS:
					matchedDN = pdn.bv_val;
					/* fail over to next case */
	
				default:
					rs->sr_err = LDAP_NO_SUCH_OBJECT;
					rs->sr_matched = matchedDN;
					goto done;
				} 
			}
		}
	}

done:;
	backsql_FreeRow_x( &row, op->o_tmpmemctx );

	Debug( LDAP_DEBUG_TRACE,
		"<==backsql_dn2id(\"%s\"): err=%d\n",
		ndn->bv_val, res, 0 );
	if ( sth != SQL_NULL_HSTMT ) {
		SQLFreeStmt( sth, SQL_DROP );
	}

	if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
		ch_free( realndn.bv_val );
	}

	return res;
}
Ejemplo n.º 14
0
int
backsql_modrdn( Operation *op, SlapReply *rs )
{
	backsql_info		*bi = (backsql_info*)op->o_bd->be_private;
	SQLHDBC			dbh = SQL_NULL_HDBC;
	SQLHSTMT		sth = SQL_NULL_HSTMT;
	RETCODE			rc;
	backsql_entryID		e_id = BACKSQL_ENTRYID_INIT,
				n_id = BACKSQL_ENTRYID_INIT;
	backsql_srch_info	bsi = { 0 };
	backsql_oc_map_rec	*oc = NULL;
	struct berval		pdn = BER_BVNULL, pndn = BER_BVNULL,
				*new_pdn = NULL, *new_npdn = NULL,
				new_dn = BER_BVNULL, new_ndn = BER_BVNULL,
				realnew_dn = BER_BVNULL;
	Entry			r = { 0 },
				p = { 0 },
				n = { 0 },
				*e = NULL;
	int			manageDSAit = get_manageDSAit( op );
	struct berval		*newSuperior = op->oq_modrdn.rs_newSup;
 
	Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", "
			"newrdn=\"%s\", newSuperior=\"%s\"\n",
			op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val, 
			newSuperior ? newSuperior->bv_val : "(NULL)" );

	rs->sr_err = backsql_get_db_conn( op, &dbh );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"could not get connection handle - exiting\n", 
			0, 0, 0 );
		rs->sr_text = ( rs->sr_err == LDAP_OTHER )
			?  "SQL-backend error" : NULL;
		e = NULL;
		goto done;
	}

	bsi.bsi_e = &r;
	rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
			LDAP_SCOPE_BASE, 
			(time_t)(-1), NULL, dbh, op, rs,
			slap_anlist_all_attributes,
			( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
	switch ( rs->sr_err ) {
	case LDAP_SUCCESS:
		break;

	case LDAP_REFERRAL:
		if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
				dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
		{
			rs->sr_err = LDAP_SUCCESS;
			rs->sr_text = NULL;
			rs->sr_matched = NULL;
			if ( rs->sr_ref ) {
				ber_bvarray_free( rs->sr_ref );
				rs->sr_ref = NULL;
			}
			break;
		}
		e = &r;
		/* fallthru */

	default:
		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
			"could not retrieve modrdnDN ID - no such entry\n", 
			0, 0, 0 );
		if ( !BER_BVISNULL( &r.e_nname ) ) {
			/* FIXME: should always be true! */
			e = &r;

		} else {
			e = NULL;
		}
		goto done;
	}

#ifdef BACKSQL_ARBITRARY_KEY
	Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): entry id=%s\n",
		e_id.eid_id.bv_val, 0, 0 );
#else /* ! BACKSQL_ARBITRARY_KEY */
	Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): entry id=%ld\n",
		e_id.eid_id, 0, 0 );
#endif /* ! BACKSQL_ARBITRARY_KEY */

	if ( get_assert( op ) &&
			( test_filter( op, &r, get_assertion( op ) )
			  != LDAP_COMPARE_TRUE ) )
	{
		rs->sr_err = LDAP_ASSERTION_FAILED;
		e = &r;
		goto done;
	}

	if ( backsql_has_children( op, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"entry \"%s\" has children\n",
			op->o_req_dn.bv_val, 0, 0 );
		rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
		rs->sr_text = "subtree rename not supported";
		e = &r;
		goto done;
	}

	/*
	 * Check for entry access to target
	 */
	if ( !access_allowed( op, &r, slap_schema.si_ad_entry, 
				NULL, ACL_WRITE, NULL ) ) {
		Debug( LDAP_DEBUG_TRACE, "   no access to entry\n", 0, 0, 0 );
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		goto done;
	}

	dnParent( &op->o_req_dn, &pdn );
	dnParent( &op->o_req_ndn, &pndn );

	/*
	 * namingContext "" is not supported
	 */
	if ( BER_BVISEMPTY( &pdn ) ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"parent is \"\" - aborting\n", 0, 0, 0 );
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		rs->sr_text = "not allowed within namingContext";
		e = NULL;
		goto done;
	}

	/*
	 * Check for children access to parent
	 */
	bsi.bsi_e = &p;
	e_id = bsi.bsi_base_id;
	memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
	rs->sr_err = backsql_init_search( &bsi, &pndn,
			LDAP_SCOPE_BASE, 
			(time_t)(-1), NULL, dbh, op, rs,
			slap_anlist_all_attributes,
			BACKSQL_ISF_GET_ENTRY );

#ifdef BACKSQL_ARBITRARY_KEY
	Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
		"old parent entry id is %s\n",
		bsi.bsi_base_id.eid_id.bv_val, 0, 0 );
#else /* ! BACKSQL_ARBITRARY_KEY */
	Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
		"old parent entry id is %ld\n",
		bsi.bsi_base_id.eid_id, 0, 0 );
#endif /* ! BACKSQL_ARBITRARY_KEY */

	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
			"could not retrieve renameDN ID - no such entry\n", 
			0, 0, 0 );
		e = &p;
		goto done;
	}

	if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL,
			newSuperior ? ACL_WDEL : ACL_WRITE, NULL ) )
	{
		Debug( LDAP_DEBUG_TRACE, "   no access to parent\n", 0, 0, 0 );
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		goto done;
	}

	if ( newSuperior ) {
		(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
		
		/*
		 * namingContext "" is not supported
		 */
		if ( BER_BVISEMPTY( newSuperior ) ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
				"newSuperior is \"\" - aborting\n", 0, 0, 0 );
			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
			rs->sr_text = "not allowed within namingContext";
			e = NULL;
			goto done;
		}

		new_pdn = newSuperior;
		new_npdn = op->oq_modrdn.rs_nnewSup;

		/*
		 * Check for children access to new parent
		 */
		bsi.bsi_e = &n;
		rs->sr_err = backsql_init_search( &bsi, new_npdn,
				LDAP_SCOPE_BASE, 
				(time_t)(-1), NULL, dbh, op, rs,
				slap_anlist_all_attributes,
				( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
				"could not retrieve renameDN ID - no such entry\n", 
				0, 0, 0 );
			e = &n;
			goto done;
		}

		n_id = bsi.bsi_base_id;

#ifdef BACKSQL_ARBITRARY_KEY
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"new parent entry id=%s\n",
			n_id.eid_id.bv_val, 0, 0 );
#else /* ! BACKSQL_ARBITRARY_KEY */
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"new parent entry id=%ld\n",
			n_id.eid_id, 0, 0 );
#endif /* ! BACKSQL_ARBITRARY_KEY */

		if ( !access_allowed( op, &n, slap_schema.si_ad_children, 
					NULL, ACL_WADD, NULL ) ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
					"no access to new parent \"%s\"\n", 
					new_pdn->bv_val, 0, 0 );
			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
			e = &n;
			goto done;
		}

	} else {
		n_id = bsi.bsi_base_id;
		new_pdn = &pdn;
		new_npdn = &pndn;
	}

	memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );

	if ( newSuperior && dn_match( &pndn, new_npdn ) ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"newSuperior is equal to old parent - ignored\n",
			0, 0, 0 );
		newSuperior = NULL;
	}

	if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"newSuperior is equal to entry being moved "
			"- aborting\n", 0, 0, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "newSuperior is equal to old DN";
		e = &r;
		goto done;
	}

	build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn,
			op->o_tmpmemctx );
	build_new_dn( &new_ndn, new_npdn, &op->oq_modrdn.rs_nnewrdn,
			op->o_tmpmemctx );
	
	Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): new entry dn is \"%s\"\n",
			new_dn.bv_val, 0, 0 );

	realnew_dn = new_dn;
	if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(\"%s\"): "
			"backsql_api_dn2odbc(\"%s\") failed\n", 
			op->o_req_dn.bv_val, realnew_dn.bv_val, 0 );
		SQLFreeStmt( sth, SQL_DROP );

		rs->sr_text = "SQL-backend error";
		rs->sr_err = LDAP_OTHER;
		e = NULL;
		goto done;
	}

	Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
		"executing renentry_stmt\n", 0, 0, 0 );

	rc = backsql_Prepare( dbh, &sth, bi->sql_renentry_stmt, 0 );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_modrdn(): "
			"error preparing renentry_stmt\n", 0, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, 
				sth, rc );

		rs->sr_text = "SQL-backend error";
		rs->sr_err = LDAP_OTHER;
		e = NULL;
		goto done;
	}

	rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_add_attr(): "
			"error binding DN parameter for objectClass %s\n",
			oc->bom_oc->soc_cname.bv_val, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, 
			sth, rc );
		SQLFreeStmt( sth, SQL_DROP );

		rs->sr_text = "SQL-backend error";
		rs->sr_err = LDAP_OTHER;
		e = NULL;
		goto done;
	}

	rc = backsql_BindParamID( sth, 2, SQL_PARAM_INPUT, &n_id.eid_id );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_add_attr(): "
			"error binding parent ID parameter for objectClass %s\n",
			oc->bom_oc->soc_cname.bv_val, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, 
			sth, rc );
		SQLFreeStmt( sth, SQL_DROP );

		rs->sr_text = "SQL-backend error";
		rs->sr_err = LDAP_OTHER;
		e = NULL;
		goto done;
	}

	rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &e_id.eid_keyval );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_add_attr(): "
			"error binding entry ID parameter for objectClass %s\n",
			oc->bom_oc->soc_cname.bv_val, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, 
			sth, rc );
		SQLFreeStmt( sth, SQL_DROP );

		rs->sr_text = "SQL-backend error";
		rs->sr_err = LDAP_OTHER;
		e = NULL;
		goto done;
	}

	rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_id );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_add_attr(): "
			"error binding ID parameter for objectClass %s\n",
			oc->bom_oc->soc_cname.bv_val, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, 
			sth, rc );
		SQLFreeStmt( sth, SQL_DROP );

		rs->sr_text = "SQL-backend error";
		rs->sr_err = LDAP_OTHER;
		e = NULL;
		goto done;
	}

	rc = SQLExecute( sth );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
			"could not rename ldap_entries record\n", 0, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
		SQLFreeStmt( sth, SQL_DROP );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "SQL-backend error";
		e = NULL;
		goto done;
	}
	SQLFreeStmt( sth, SQL_DROP );

	assert( op->orr_modlist != NULL );

	slap_mods_opattrs( op, &op->orr_modlist, 1 );

	assert( e_id.eid_oc != NULL );
	oc = e_id.eid_oc;
	rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist );
	slap_graduate_commit_csn( op );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		e = &r;
		goto done;
	}

	if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
		char		textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };

		backsql_entry_clean( op, &r );
		(void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );

		bsi.bsi_e = &r;
		rs->sr_err = backsql_init_search( &bsi, &new_ndn,
				LDAP_SCOPE_BASE, 
				(time_t)(-1), NULL, dbh, op, rs,
				slap_anlist_all_attributes,
				( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
		switch ( rs->sr_err ) {
		case LDAP_SUCCESS:
			break;

		case LDAP_REFERRAL:
			if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
					dn_match( &new_ndn, &bsi.bsi_e->e_nname ) )
			{
				rs->sr_err = LDAP_SUCCESS;
				rs->sr_text = NULL;
				rs->sr_matched = NULL;
				if ( rs->sr_ref ) {
					ber_bvarray_free( rs->sr_ref );
					rs->sr_ref = NULL;
				}
				break;
			}
			e = &r;
			/* fallthru */

		default:
			Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
				"could not retrieve modrdnDN ID - no such entry\n", 
				0, 0, 0 );
			if ( !BER_BVISNULL( &r.e_nname ) ) {
				/* FIXME: should always be true! */
				e = &r;

			} else {
				e = NULL;
			}
			goto done;
		}

		e_id = bsi.bsi_base_id;

		rs->sr_err = entry_schema_check( op, &r, NULL, 0, 0,
			&rs->sr_text, textbuf, sizeof( textbuf ) );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(\"%s\"): "
				"entry failed schema check -- aborting\n",
				r.e_name.bv_val, 0, 0 );
			e = NULL;
			goto done;
		}
	}

done:;
	if ( e != NULL ) {
		if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
					ACL_DISCLOSE, NULL ) )
		{
			rs->sr_err = LDAP_NO_SUCH_OBJECT;
			rs->sr_text = NULL;
			rs->sr_matched = NULL;
			if ( rs->sr_ref ) {
				ber_bvarray_free( rs->sr_ref );
				rs->sr_ref = NULL;
			}
		}
	}

	/*
	 * Commit only if all operations succeed
	 */
	if ( sth != SQL_NULL_HSTMT ) {
		SQLUSMALLINT	CompletionType = SQL_ROLLBACK;
	
		if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
			CompletionType = SQL_COMMIT;
		}

		SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
	}

	if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
		rs->sr_err = LDAP_X_NO_OPERATION;
	}

	send_ldap_result( op, rs );
	slap_graduate_commit_csn( op );

	if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != new_dn.bv_val ) {
		ch_free( realnew_dn.bv_val );
	}

	if ( !BER_BVISNULL( &new_dn ) ) {
		slap_sl_free( new_dn.bv_val, op->o_tmpmemctx );
	}
	
	if ( !BER_BVISNULL( &new_ndn ) ) {
		slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx );
	}
	
	if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
		(void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
	}

	if ( !BER_BVISNULL( &n_id.eid_ndn ) ) {
		(void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx );
	}

	if ( !BER_BVISNULL( &r.e_nname ) ) {
		backsql_entry_clean( op, &r );
	}

	if ( !BER_BVISNULL( &p.e_nname ) ) {
		backsql_entry_clean( op, &p );
	}

	if ( !BER_BVISNULL( &n.e_nname ) ) {
		backsql_entry_clean( op, &n );
	}

	if ( rs->sr_ref ) {
		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
	}

	Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );

	return rs->sr_err;
}
Ejemplo n.º 15
0
int
slap_parse_modlist(
	Operation *op,
	SlapReply *rs,
	BerElement *ber,
	req_modify_s *ms )
{
	ber_tag_t	tag;
	ber_len_t	len;
	char		*last;
	Modifications	**modtail = &ms->rs_mods.rs_modlist;

	ms->rs_mods.rs_modlist = NULL;
	ms->rs_increment = 0;

	rs->sr_err = LDAP_SUCCESS;

	/* collect modifications & save for later */
	for ( tag = ber_first_element( ber, &len, &last );
		tag != LBER_DEFAULT;
		tag = ber_next_element( ber, &len, last ) )
	{
		ber_int_t mop;
		Modifications tmp, *mod;

		tmp.sml_nvalues = NULL;

		if ( ber_scanf( ber, "{e{m[W]}}", &mop,
		    &tmp.sml_type, &tmp.sml_values ) == LBER_ERROR )
		{
			rs->sr_text = "decoding modlist error";
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		mod = (Modifications *) ch_malloc( sizeof(Modifications) );
		mod->sml_op = mop;
		mod->sml_flags = 0;
		mod->sml_type = tmp.sml_type;
		mod->sml_values = tmp.sml_values;
		mod->sml_nvalues = NULL;
		mod->sml_desc = NULL;
		mod->sml_next = NULL;
		*modtail = mod;

		switch( mop ) {
		case LDAP_MOD_ADD:
			if ( mod->sml_values == NULL ) {
				rs->sr_text = "modify/add operation requires values";
				rs->sr_err = LDAP_PROTOCOL_ERROR;
				goto done;
			}

			/* fall through */

		case LDAP_MOD_DELETE:
		case LDAP_MOD_REPLACE:
			break;

		case LDAP_MOD_INCREMENT:
			if( op->o_protocol >= LDAP_VERSION3 ) {
				ms->rs_increment++;
				if ( mod->sml_values == NULL ) {
					rs->sr_text = "modify/increment operation requires value";
					rs->sr_err = LDAP_PROTOCOL_ERROR;
					goto done;
				}

				if ( !BER_BVISNULL( &mod->sml_values[ 1 ] ) ) {
					rs->sr_text = "modify/increment operation requires single value";
					rs->sr_err = LDAP_PROTOCOL_ERROR;
					goto done;
				}

				break;
			}
			/* fall thru */

		default:
			rs->sr_text = "unrecognized modify operation";
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		modtail = &mod->sml_next;
	}
	*modtail = NULL;

done:
	if ( rs->sr_err != LDAP_SUCCESS ) {
		slap_mods_free( ms->rs_mods.rs_modlist, 1 );
		ms->rs_mods.rs_modlist = NULL;
		ms->rs_increment = 0;
	}

	return rs->sr_err;
}
Ejemplo n.º 16
0
static int sssvlv_op_response(
	Operation	*op,
	SlapReply	*rs )
{
	sort_ctrl *sc = op->o_controls[sss_cid];
	sort_op *so = op->o_callback->sc_private;

	if ( rs->sr_type == REP_SEARCH ) {
		int i;
		size_t len;
		sort_node *sn, *sn2;
		struct berval *bv;
		char *ptr;

		len = sizeof(sort_node) + sc->sc_nkeys * sizeof(struct berval) +
			rs->sr_entry->e_nname.bv_len + 1;
		sn = op->o_tmpalloc( len, op->o_tmpmemctx );
		sn->sn_vals = (struct berval *)(sn+1);

		/* Build tmp list of key values */
		for ( i=0; i<sc->sc_nkeys; i++ ) {
			Attribute *a = attr_find( rs->sr_entry->e_attrs,
				sc->sc_keys[i].sk_ad );
			if ( a ) {
				if ( a->a_numvals > 1 ) {
					bv = select_value( a, &sc->sc_keys[i] );
				} else {
					bv = a->a_nvals;
				}
				sn->sn_vals[i] = *bv;
				len += bv->bv_len + 1;
			} else {
				BER_BVZERO( &sn->sn_vals[i] );
			}
		}

		/* Now dup into regular memory */
		sn2 = ch_malloc( len );
		sn2->sn_vals = (struct berval *)(sn2+1);
		memcpy( sn2->sn_vals, sn->sn_vals,
				sc->sc_nkeys * sizeof(struct berval));

		ptr = (char *)(sn2->sn_vals + sc->sc_nkeys);
		sn2->sn_dn.bv_val = ptr;
		sn2->sn_dn.bv_len = rs->sr_entry->e_nname.bv_len;
		memcpy( ptr, rs->sr_entry->e_nname.bv_val,
			rs->sr_entry->e_nname.bv_len );
		ptr += rs->sr_entry->e_nname.bv_len;
		*ptr++ = '\0';
		for ( i=0; i<sc->sc_nkeys; i++ ) {
			if ( !BER_BVISNULL( &sn2->sn_vals[i] )) {
				memcpy(ptr, sn2->sn_vals[i].bv_val, sn2->sn_vals[i].bv_len);
				sn2->sn_vals[i].bv_val = ptr;
				ptr += sn2->sn_vals[i].bv_len;
				*ptr++ = '\0';
			}
		}
		op->o_tmpfree( sn, op->o_tmpmemctx );
		sn = sn2;
		sn->sn_conn = op->o_conn->c_conn_idx;
		sn->sn_session = find_session_by_so( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, so );

		/* Insert into the AVL tree */
		tavl_insert(&(so->so_tree), sn, node_insert, avl_dup_error);

		so->so_nentries++;

		/* Collected the keys so that they can be sorted.  Thus, stop
		 * the entry from propagating.
		 */
		rs->sr_err = LDAP_SUCCESS;
	}
	else if ( rs->sr_type == REP_RESULT ) {
		/* Remove serversort response callback.
		 * We don't want the entries that we are about to send to be
		 * processed by serversort response again.
		 */
		if ( op->o_callback->sc_response == sssvlv_op_response ) {
			op->o_callback = op->o_callback->sc_next;
		}

		send_entry( op, rs, so );
		send_result( op, rs, so );
	}

	return rs->sr_err;
}
Ejemplo n.º 17
0
int
do_modify(
    Operation	*op,
    SlapReply	*rs )
{
	struct berval dn = BER_BVNULL;
	char		textbuf[ SLAP_TEXT_BUFLEN ];
	size_t		textlen = sizeof( textbuf );
#ifdef LDAP_DEBUG
	Modifications	*tmp;
#endif

	Debug( LDAP_DEBUG_TRACE, "%s do_modify\n",
		op->o_log_prefix, 0, 0 );
	/*
	 * Parse the modify request.  It looks like this:
	 *
	 *	ModifyRequest := [APPLICATION 6] SEQUENCE {
	 *		name	DistinguishedName,
	 *		mods	SEQUENCE OF SEQUENCE {
	 *			operation	ENUMERATED {
	 *				add	(0),
	 *				delete	(1),
	 *				replace	(2)
	 *			},
	 *			modification	SEQUENCE {
	 *				type	AttributeType,
	 *				values	SET OF AttributeValue
	 *			}
	 *		}
	 *	}
	 */

	if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: ber_scanf failed\n",
			op->o_log_prefix, 0, 0 );
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
		return SLAPD_DISCONNECT;
	}

	Debug( LDAP_DEBUG_ARGS, "%s do_modify: dn (%s)\n",
		op->o_log_prefix, dn.bv_val, 0 );

	rs->sr_err = slap_parse_modlist( op, rs, op->o_ber, &op->oq_modify );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n",
			op->o_log_prefix, rs->sr_err, rs->sr_text );
		goto cleanup;
	}

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

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

	op->orm_no_opattrs = 0;

#ifdef LDAP_DEBUG
	Debug( LDAP_DEBUG_ARGS, "%s modifications:\n",
			op->o_log_prefix, 0, 0 );

	for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) {
		Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
			tmp->sml_op == LDAP_MOD_ADD ? "add" :
				(tmp->sml_op == LDAP_MOD_INCREMENT ? "increment" :
				(tmp->sml_op == LDAP_MOD_DELETE ? "delete" :
					"replace")), tmp->sml_type.bv_val, 0 );

		if ( tmp->sml_values == NULL ) {
			Debug( LDAP_DEBUG_ARGS, "%s\n",
			   "\t\tno values", NULL, NULL );
		} else if ( BER_BVISNULL( &tmp->sml_values[ 0 ] ) ) {
			Debug( LDAP_DEBUG_ARGS, "%s\n",
			   "\t\tzero values", NULL, NULL );
		} else if ( BER_BVISNULL( &tmp->sml_values[ 1 ] ) ) {
			Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n",
			   "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL );
		} else {
			Debug( LDAP_DEBUG_ARGS, "%s\n",
			   "\t\tmultiple values", NULL, NULL );
		}
	}

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

		Statslog( LDAP_DEBUG_STATS, "%s MOD dn=\"%s\"\n",
			op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );

		for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) {
			if (len + 1 + tmp->sml_type.bv_len > sizeof(abuf)) {
				Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n",
				    op->o_log_prefix, abuf, 0, 0, 0 );

				len = 0;
				ptr = abuf;

				if( 1 + tmp->sml_type.bv_len > sizeof(abuf)) {
					Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n",
						op->o_log_prefix, tmp->sml_type.bv_val, 0, 0, 0 );
					continue;
				}
			}
			if (len) {
				*ptr++ = ' ';
				len++;
			}
			ptr = lutil_strcopy(ptr, tmp->sml_type.bv_val);
			len += tmp->sml_type.bv_len;
		}
		if (len) {
			Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n",
	    			op->o_log_prefix, abuf, 0, 0, 0 );
		}
	}
#endif	/* LDAP_DEBUG */

	rs->sr_err = slap_mods_check( op, op->orm_modlist,
		&rs->sr_text, textbuf, textlen, NULL );

	if ( rs->sr_err != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

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

#ifdef LDAP_X_TXN
	if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
		/* skip cleanup */
		return rs->sr_err;
	}
#endif

cleanup:
	op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
	op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
	if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 );

	return rs->sr_err;
}
Ejemplo n.º 18
0
void
slapi_int_connection_done_pb( Slapi_PBlock *pb )
{
	Connection		*conn;
	Operation		*op;

	PBLOCK_ASSERT_INTOP( pb, 0 );

	conn = pb->pb_conn;
	op = pb->pb_op;

	/* free allocated DNs */
	if ( !BER_BVISNULL( &op->o_dn ) )
		op->o_tmpfree( op->o_dn.bv_val, op->o_tmpmemctx );
	if ( !BER_BVISNULL( &op->o_ndn ) )
		op->o_tmpfree( op->o_ndn.bv_val, op->o_tmpmemctx );

	if ( !BER_BVISNULL( &op->o_req_dn ) )
		op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
	if ( !BER_BVISNULL( &op->o_req_ndn ) )
		op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );

	switch ( op->o_tag ) {
	case LDAP_REQ_MODRDN:
		if ( !BER_BVISNULL( &op->orr_newrdn ))
			op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx );
		if ( !BER_BVISNULL( &op->orr_nnewrdn ))
			op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx );
		if ( op->orr_newSup != NULL ) {
			assert( !BER_BVISNULL( op->orr_newSup ) );
			op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx );
			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
		}
		if ( op->orr_nnewSup != NULL ) {
			assert( !BER_BVISNULL( op->orr_nnewSup ) );
			op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx );
			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
		}
		slap_mods_free( op->orr_modlist, 1 );
		break;
	case LDAP_REQ_ADD:
		slap_mods_free( op->ora_modlist, 0 );
		break;
	case LDAP_REQ_MODIFY:
		slap_mods_free( op->orm_modlist, 1 );
		break;
	case LDAP_REQ_SEARCH:
		if ( op->ors_attrs != NULL ) {
			op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx );
			op->ors_attrs = NULL;
		}
		break;
	default:
		break;
	}

	slapi_ch_free_string( &conn->c_authmech.bv_val );
	slapi_ch_free_string( &conn->c_dn.bv_val );
	slapi_ch_free_string( &conn->c_ndn.bv_val );
	slapi_ch_free_string( &conn->c_peer_domain.bv_val );
	slapi_ch_free_string( &conn->c_peer_name.bv_val );

	if ( conn->c_sb != NULL ) {
		ber_sockbuf_free( conn->c_sb );
	}

	slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op );
	slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, conn );

	slapi_ch_free( (void **)&pb->pb_op->o_callback );
	slapi_ch_free( (void **)&pb->pb_op );
	slapi_ch_free( (void **)&pb->pb_conn );
	slapi_ch_free( (void **)&pb->pb_rs );
}
Ejemplo n.º 19
0
/* Called for all modify and modrdn ops. If the current op was replicated
 * from elsewhere, all of the attrs should already be present.
 */
void slap_mods_opattrs(
	Operation *op,
	Modifications **modsp,
	int manage_ctxcsn )
{
	struct berval name, timestamp, csn = BER_BVNULL;
	struct berval nname;
	char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
	char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
	Modifications *mod, **modtail, *modlast;
	int gotcsn = 0, gotmname = 0, gotmtime = 0;

	if ( SLAP_LASTMOD( op->o_bd ) && !op->orm_no_opattrs ) {
		char *ptr;
		timestamp.bv_val = timebuf;
		for ( modtail = modsp; *modtail; modtail = &(*modtail)->sml_next ) {
			if ( (*modtail)->sml_op != LDAP_MOD_ADD &&
				(*modtail)->sml_op != SLAP_MOD_SOFTADD &&
				(*modtail)->sml_op != LDAP_MOD_REPLACE )
			{
				continue;
			}

			if ( (*modtail)->sml_desc == slap_schema.si_ad_entryCSN )
			{
				csn = (*modtail)->sml_values[0];
				gotcsn = 1;

			} else if ( (*modtail)->sml_desc == slap_schema.si_ad_modifiersName )
			{
				gotmname = 1;

			} else if ( (*modtail)->sml_desc == slap_schema.si_ad_modifyTimestamp )
			{
				gotmtime = 1;
			}
		}

		if ( BER_BVISEMPTY( &op->o_csn )) {
			if ( !gotcsn ) {
				csn.bv_val = csnbuf;
				csn.bv_len = sizeof( csnbuf );
				slap_get_csn( op, &csn, manage_ctxcsn );

			} else {
				if ( manage_ctxcsn ) {
					slap_queue_csn( op, &csn );
				}
			}

		} else {
			csn = op->o_csn;
		}

		ptr = ber_bvchr( &csn, '#' );
		if ( ptr ) {
			timestamp.bv_len = STRLENOF("YYYYMMDDHHMMSSZ");
			AC_MEMCPY( timebuf, csn.bv_val, timestamp.bv_len );
			timebuf[timestamp.bv_len-1] = 'Z';
			timebuf[timestamp.bv_len] = '\0';

		} else {
			time_t now = slap_get_time();

			timestamp.bv_len = sizeof(timebuf);

			slap_timestamp( &now, &timestamp );
		}

		if ( BER_BVISEMPTY( &op->o_dn ) ) {
			BER_BVSTR( &name, SLAPD_ANONYMOUS );
			nname = name;

		} else {
			name = op->o_dn;
			nname = op->o_ndn;
		}

		if ( !gotcsn ) {
			mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
			mod->sml_op = LDAP_MOD_REPLACE;
			mod->sml_flags = SLAP_MOD_INTERNAL;
			mod->sml_next = NULL;
			BER_BVZERO( &mod->sml_type );
			mod->sml_desc = slap_schema.si_ad_entryCSN;
			mod->sml_numvals = 1;
			mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_values[0], &csn );
			BER_BVZERO( &mod->sml_values[1] );
			assert( !BER_BVISNULL( &mod->sml_values[0] ) );
			mod->sml_nvalues = NULL;
			*modtail = mod;
			modlast = mod;
			modtail = &mod->sml_next;
		}

		if ( !gotmname ) {
			mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
			mod->sml_op = LDAP_MOD_REPLACE;
			mod->sml_flags = SLAP_MOD_INTERNAL;
			mod->sml_next = NULL;
			BER_BVZERO( &mod->sml_type );
			mod->sml_desc = slap_schema.si_ad_modifiersName;
			mod->sml_numvals = 1;
			mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_values[0], &name );
			BER_BVZERO( &mod->sml_values[1] );
			assert( !BER_BVISNULL( &mod->sml_values[0] ) );
			mod->sml_nvalues =
				(BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_nvalues[0], &nname );
			BER_BVZERO( &mod->sml_nvalues[1] );
			assert( !BER_BVISNULL( &mod->sml_nvalues[0] ) );
			*modtail = mod;
			modtail = &mod->sml_next;
		}

		if ( !gotmtime ) {
			mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
			mod->sml_op = LDAP_MOD_REPLACE;
			mod->sml_flags = SLAP_MOD_INTERNAL;
			mod->sml_next = NULL;
			BER_BVZERO( &mod->sml_type );
			mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
			mod->sml_numvals = 1;
			mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_values[0], &timestamp );
			BER_BVZERO( &mod->sml_values[1] );
			assert( !BER_BVISNULL( &mod->sml_values[0] ) );
			mod->sml_nvalues = NULL;
			*modtail = mod;
			modtail = &mod->sml_next;
		}
	}
}
Ejemplo n.º 20
0
int
slapi_add_internal_pb( Slapi_PBlock *pb )
{
	SlapReply		*rs;
	Slapi_Entry		*entry_orig = NULL;
	OpExtraDB oex;
	int rc;

	if ( pb == NULL ) {
		return -1;
	}

	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_ADD );

	rs = pb->pb_rs;

	entry_orig = pb->pb_op->ora_e;
	pb->pb_op->ora_e = NULL;

	/*
	 * The caller can specify a new entry, or a target DN and set
	 * of modifications, but not both.
	 */
	if ( entry_orig != NULL ) {
		if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
			rs->sr_err = LDAP_PARAM_ERROR;
			goto cleanup;
		}

		assert( BER_BVISNULL( &pb->pb_op->o_req_dn ) ); /* shouldn't get set */
		ber_dupbv( &pb->pb_op->o_req_dn, &entry_orig->e_name );
		ber_dupbv( &pb->pb_op->o_req_ndn, &entry_orig->e_nname );
	} else if ( pb->pb_op->ora_modlist == NULL || BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
		rs->sr_err = LDAP_PARAM_ERROR;
		goto cleanup;
	}

	pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) );
	ber_dupbv( &pb->pb_op->ora_e->e_name,  &pb->pb_op->o_req_dn );
	ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn );

	if ( entry_orig != NULL ) {
		assert( pb->pb_op->ora_modlist == NULL );

		rs->sr_err = slap_entry2mods( entry_orig, &pb->pb_op->ora_modlist,
			&rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			goto cleanup;
		}
	} else {
		assert( pb->pb_op->ora_modlist != NULL );
	}

	rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->ora_modlist, &rs->sr_text,
		pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
	if ( rs->sr_err != LDAP_SUCCESS ) {
                goto cleanup;
        }

	/* Duplicate the values, because we may call slapi_entry_free() */
	rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e,
		1, 0, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		goto cleanup;
	}

	oex.oe.oe_key = (void *)do_add;
	oex.oe_db = NULL;
	LDAP_SLIST_INSERT_HEAD(&pb->pb_op->o_extra, &oex.oe, oe_next);
	rc = slapi_int_func_internal_pb( pb, op_add );
	LDAP_SLIST_REMOVE(&pb->pb_op->o_extra, &oex.oe, OpExtra, oe_next);

	if ( !rc ) {
		if ( pb->pb_op->ora_e != NULL && oex.oe_db != NULL ) {
			BackendDB	*bd = pb->pb_op->o_bd;

			pb->pb_op->o_bd = oex.oe_db;
			be_entry_release_w( pb->pb_op, pb->pb_op->ora_e );
			pb->pb_op->ora_e = NULL;
			pb->pb_op->o_bd = bd;
		}
	}

cleanup:

	if ( pb->pb_op->ora_e != NULL ) {
		slapi_entry_free( pb->pb_op->ora_e );
		pb->pb_op->ora_e = NULL;
	}
	if ( entry_orig != NULL ) {
		pb->pb_op->ora_e = entry_orig;
		slap_mods_free( pb->pb_op->ora_modlist, 1 );
		pb->pb_op->ora_modlist = NULL;
	}

	return 0;
}
Ejemplo n.º 21
0
int
do_extended(
    Operation	*op,
    SlapReply	*rs
)
{
	struct berval reqdata = {0, NULL};
	ber_len_t len;

	Debug( LDAP_DEBUG_TRACE, "%s do_extended\n",
		op->o_log_prefix, 0, 0 );

	if( op->o_protocol < LDAP_VERSION3 ) {
		Debug( LDAP_DEBUG_ANY, "%s do_extended: protocol version (%d) too low\n",
			op->o_log_prefix, op->o_protocol, 0 );
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "requires LDAPv3" );
		rs->sr_err = SLAPD_DISCONNECT;
		goto done;
	}

	if ( ber_scanf( op->o_ber, "{m" /*}*/, &op->ore_reqoid ) == LBER_ERROR ) {
		Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n",
			op->o_log_prefix, 0, 0 );
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
		rs->sr_err = SLAPD_DISCONNECT;
		goto done;
	}

	if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) {
		if( ber_scanf( op->o_ber, "m", &reqdata ) == LBER_ERROR ) {
			Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n",
				op->o_log_prefix, 0, 0 );
			send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
			rs->sr_err = SLAPD_DISCONNECT;
			goto done;
		}
	}

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

	Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n",
	    op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 );

	/* check for controls inappropriate for all extended operations */
	if( get_manageDSAit( op ) == SLAP_CONTROL_CRITICAL ) {
		send_ldap_error( op, rs,
			LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
			"manageDSAit control inappropriate" );
		goto done;
	}

	/* FIXME: temporary? */
	if ( reqdata.bv_val ) {
		op->ore_reqdata = &reqdata;
	}

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

	/* clean up in case some overlay set them? */
	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
		if ( !BER_BVISNULL( &op->o_req_dn )
			&& op->o_req_ndn.bv_val != op->o_req_dn.bv_val )
		{
			op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
		}
		op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &op->o_req_dn );
		BER_BVZERO( &op->o_req_ndn );
	}

done:
	return rs->sr_err;
}
Ejemplo n.º 22
0
static int
test_ava_vrFilter(
	Operation	*op,
	Attribute	*a,
	AttributeAssertion *ava,
	int		type,
	char 		***e_flags )
{
	int 		i, j;

	for ( i=0; a != NULL; a = a->a_next, i++ ) {
		MatchingRule *mr;
		struct berval *bv;
	
		if ( !is_ad_subtype( a->a_desc, ava->aa_desc ) ) {
			continue;
		}

		switch ( type ) {
		case LDAP_FILTER_APPROX:
			mr = a->a_desc->ad_type->sat_approx;
			if( mr != NULL ) break;
			/* use EQUALITY matching rule if no APPROX rule */

		case LDAP_FILTER_EQUALITY:
			mr = a->a_desc->ad_type->sat_equality;
			break;
		
		case LDAP_FILTER_GE:
		case LDAP_FILTER_LE:
			mr = a->a_desc->ad_type->sat_ordering;
			break;

		default:
			mr = NULL;
		}

		if( mr == NULL ) continue;

		bv = a->a_nvals;
		for ( j=0; !BER_BVISNULL( bv ); bv++, j++ ) {
			int rc, match;
			const char *text;

			rc = value_match( &match, a->a_desc, mr, 0,
				bv, &ava->aa_value, &text );
			if( rc != LDAP_SUCCESS ) return rc;

			switch ( type ) {
			case LDAP_FILTER_EQUALITY:
			case LDAP_FILTER_APPROX:
				if ( match == 0 ) {
					(*e_flags)[i][j] = 1;
				}
				break;
	
			case LDAP_FILTER_GE:
				if ( match >= 0 ) {
					(*e_flags)[i][j] = 1;
				}
				break;
	
			case LDAP_FILTER_LE:
				if ( match <= 0 ) {
					(*e_flags)[i][j] = 1;
				}
				break;
			}
		}
	}
	return LDAP_SUCCESS;
}
Ejemplo n.º 23
0
static int
dupent_parseCtrl (
	Operation *op,
	SlapReply *rs,
	LDAPControl *ctrl )
{
	ber_tag_t tag;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	ber_len_t len;
	BerVarray AttributeDescriptionList = NULL;
	ber_len_t cnt = sizeof(struct berval);
	ber_len_t off = 0;
	ber_int_t PartialApplicationAllowed = 1;
	dupent_t *ds = NULL;
	int i;

	if ( op->o_dupent != SLAP_CONTROL_NONE ) {
		rs->sr_text = "Dupent control specified multiple times";
		return LDAP_PROTOCOL_ERROR;
	}

	if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
		rs->sr_text = "Dupent control value is absent";
		return LDAP_PROTOCOL_ERROR;
	}

	if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
		rs->sr_text = "Dupent control value is empty";
		return LDAP_PROTOCOL_ERROR;
	}

	ber_init2( ber, &ctrl->ldctl_value, 0 );

	/*

   DuplicateEntryRequest ::= SEQUENCE { 
        AttributeDescriptionList, -- from [RFC2251] 
        PartialApplicationAllowed BOOLEAN DEFAULT TRUE } 

        AttributeDescriptionList ::= SEQUENCE OF 
                AttributeDescription 
    
        AttributeDescription ::= LDAPString 
    
        attributeDescription = AttributeType [ ";" <options> ] 

	 */

	tag = ber_skip_tag( ber, &len );
	if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
	if ( ber_scanf( ber, "{M}", &AttributeDescriptionList, &cnt, off )
		== LBER_ERROR )
	{
		rs->sr_text = "Dupent control: dupentSpec decoding error";
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}
	tag = ber_skip_tag( ber, &len );
	if ( tag == LBER_BOOLEAN ) {
		/* NOTE: PartialApplicationAllowed is ignored, since the control
		 * can always be honored
		 */
		if ( ber_scanf( ber, "b", &PartialApplicationAllowed ) == LBER_ERROR )
		{
			rs->sr_text = "Dupent control: dupentSpec decoding error";
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
		tag = ber_skip_tag( ber, &len );
	}
	if ( len || tag != LBER_DEFAULT ) {
		rs->sr_text = "Dupent control: dupentSpec decoding error";
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	ds = (dupent_t *)op->o_tmpcalloc( 1,
		sizeof(dupent_t) + sizeof(AttributeName)*cnt,
		op->o_tmpmemctx );

	ds->ds_paa = PartialApplicationAllowed;

	if ( cnt == 0 ) {
		ds->ds_flags |= SLAP_USERATTRS_YES;

	} else {
		int c;

		ds->ds_an = (AttributeName *)&ds[ 1 ];

		for ( i = 0, c = 0; i < cnt; i++ ) {
			const char *text;
			int j;
			int rc;
			AttributeDescription *ad = NULL;

			if ( bvmatch( &AttributeDescriptionList[i],
				slap_bv_all_user_attrs ) )
			{
				if ( ds->ds_flags & SLAP_USERATTRS_YES ) {
					rs->sr_text = "Dupent control: AttributeDescription decoding error";
					rs->sr_err = LDAP_PROTOCOL_ERROR;
					goto done;
				}

				ds->ds_flags |= SLAP_USERATTRS_YES;
				continue;
			}

			rc = slap_bv2ad( &AttributeDescriptionList[i], &ad, &text );
			if ( rc != LDAP_SUCCESS ) {
				continue;
			}

			ds->ds_an[c].an_desc = ad;
			ds->ds_an[c].an_name = ad->ad_cname;

			/* FIXME: not specified; consider this an error, just in case */
			for ( j = 0; j < c; j++ ) {
				if ( ds->ds_an[c].an_desc == ds->ds_an[j].an_desc ) {
					rs->sr_text = "Dupent control: AttributeDescription must be unique within AttributeDescriptionList";
					rs->sr_err = LDAP_PROTOCOL_ERROR;
					goto done;
				}
			}

			c++;
		}

		ds->ds_nattrs = c;

		if ( ds->ds_flags & SLAP_USERATTRS_YES ) {
			/* purge user attrs */
			for ( i = 0; i < ds->ds_nattrs;  ) {
				if ( is_at_operational( ds->ds_an[i].an_desc->ad_type ) ) {
					i++;
					continue;
				}

				ds->ds_nattrs--;
				if ( i < ds->ds_nattrs ) {
					ds->ds_an[i] = ds->ds_an[ds->ds_nattrs];
				}
			}
		}
	}

	op->o_ctrldupent = (void *)ds;

	op->o_dupent = ctrl->ldctl_iscritical
		? SLAP_CONTROL_CRITICAL
		: SLAP_CONTROL_NONCRITICAL;

	rs->sr_err = LDAP_SUCCESS;

done:;
	if ( rs->sr_err != LDAP_SUCCESS ) {
		op->o_tmpfree( ds, op->o_tmpmemctx );
	}

	if ( AttributeDescriptionList != NULL ) {
		ber_memfree_x( AttributeDescriptionList, op->o_tmpmemctx );
	}

	return rs->sr_err;
}
Ejemplo n.º 24
0
static int
test_mra_vrFilter(
	Operation	*op,
	Attribute	*a,
	MatchingRuleAssertion *mra,
	char 		***e_flags )
{
	int	i, j;

	for ( i = 0; a != NULL; a = a->a_next, i++ ) {
		struct berval	*bv, assertedValue;
		int		normalize_attribute = 0;

		if ( mra->ma_desc ) {
			if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
				continue;
			}
			assertedValue = mra->ma_value;

		} else {
			int rc;
			const char	*text = NULL;

			/* check if matching is appropriate */
			if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
				continue;
			}

			rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
				SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
				&mra->ma_value, &assertedValue, &text, op->o_tmpmemctx );

			if ( rc != LDAP_SUCCESS ) continue;
		}

		/* check match */
		if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
			bv = a->a_nvals;

		} else {
			bv = a->a_vals;
			normalize_attribute = 1;
		}
					
		for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) {
			int		rc, match;
			const char	*text;
			struct berval	nbv = BER_BVNULL;

			if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
				/* see comment in filterentry.c */
				if ( mra->ma_rule->smr_normalize(
						SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
						mra->ma_rule->smr_syntax,
						mra->ma_rule,
						bv, &nbv, op->o_tmpmemctx ) != LDAP_SUCCESS )
				{
					/* FIXME: stop processing? */
					continue;
				}

			} else {
				nbv = *bv;
			}

			rc = value_match( &match, a->a_desc, mra->ma_rule, 0,
				&nbv, &assertedValue, &text );

			if ( nbv.bv_val != bv->bv_val ) {
				op->o_tmpfree( nbv.bv_val, op->o_tmpmemctx );
			}

			if ( rc != LDAP_SUCCESS ) return rc;

			if ( match == 0 ) {
				(*e_flags)[i][j] = 1;
			}
		}
	}

	return LDAP_SUCCESS;
}
Ejemplo n.º 25
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, numeric = 0;
				int j;
				size_t val = 0;
				char val_buf[SLAP_TEXT_BUFLEN] = { '\0' };

				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;

				switch (cp->type) {
					case CONSTRAINT_COUNT:
						tstr = COUNT_STR;
						val = cp->count;
						numeric = 1;
						break;
					case CONSTRAINT_SIZE:
						tstr = SIZE_STR;
						val = cp->size;
						numeric = 1;
						break;
					case CONSTRAINT_REGEX:
						tstr = REGEX_STR;
						quotes = 1;
						break;
					case CONSTRAINT_SET:
						tstr = SET_STR;
						quotes = 1;
						break;
					case CONSTRAINT_URI:
						tstr = URI_STR;
						quotes = 1;
						break;
					default:
						abort();
				}

				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=\"\"");
				}

				if (numeric) {
					int len = snprintf(val_buf, sizeof(val_buf), "%zu", val);
					if (len <= 0) {
						/* error */
						return -1;
					}
					bv.bv_len += len;
				}

				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 (numeric) {
					s = lutil_strcopy( s, val_buf );
				} else {
					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.type = CONSTRAINT_REGEX;
				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 ) {
				char *endptr;

				ap.type = CONSTRAINT_SIZE;
				ap.size = strtoull(c->argv[3], &endptr, 10);
				if ( *endptr )
					rc = ARG_BAD_CONF;
			} else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) {
				char *endptr;

				ap.type = CONSTRAINT_COUNT;
				ap.count = strtoull(c->argv[3], &endptr, 10);
				if ( *endptr )
					rc = ARG_BAD_CONF;
			} else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) {
				int err;

				ap.type = CONSTRAINT_URI;
				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 );
						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;
					}
					memmove( &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 );
				ap.type = CONSTRAINT_SET;

			} 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] + STRLENOF("restrict="), 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->type = ap.type;
				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 );
				constraint_free( &ap, 0 );
			}

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

	return rc;
}
Ejemplo n.º 26
0
static int
aa_operational( Operation *op, SlapReply *rs )
{
	Attribute		*a, **ap;
	AccessControlState	acl_state = ACL_STATE_INIT;
	struct berval		*v;
	AttributeType		**atp = NULL;
	ObjectClass		**ocp = NULL;

#define	GOT_NONE	(0x0U)
#define	GOT_C		(0x1U)
#define	GOT_CE		(0x2U)
#define	GOT_A		(0x4U)
#define	GOT_AE		(0x8U)
#define	GOT_ALL		(GOT_C|GOT_CE|GOT_A|GOT_AE)
	int		got = GOT_NONE;

	/* only add if requested */
	if ( SLAP_OPATTRS( rs->sr_attr_flags ) ) {
		got = GOT_ALL;

	} else {
		if ( ad_inlist( ad_allowedChildClasses, rs->sr_attrs ) ) {
			got |= GOT_C;
		}

		if ( ad_inlist( ad_allowedChildClassesEffective, rs->sr_attrs ) ) {
			got |= GOT_CE;
		}

		if ( ad_inlist( ad_allowedAttributes, rs->sr_attrs ) ) {
			got |= GOT_A;
		}

		if ( ad_inlist( ad_allowedAttributesEffective, rs->sr_attrs ) ) {
			got |= GOT_AE;
		}
	}

	if ( got == GOT_NONE ) {
		return SLAP_CB_CONTINUE;
	}

	/* shouldn't be called without an entry; please check */
	assert( rs->sr_entry != NULL );

	for ( ap = &rs->sr_operational_attrs; *ap != NULL; ap = &(*ap)->a_next )
		/* go to last */ ;

	/* see caveats; this is not guaranteed for all backends */
	a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass );
	if ( a == NULL ) {
		goto do_oc;
	}

	/* if client has no access to objectClass attribute; don't compute */
	if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass,
				NULL, ACL_READ, &acl_state ) )
	{
		return SLAP_CB_CONTINUE;
	}

	for ( v = a->a_nvals; !BER_BVISNULL( v ); v++ ) {
		ObjectClass	*oc = oc_bvfind( v );

		assert( oc != NULL );

		/* if client has no access to specific value, don't compute */
		if ( !access_allowed( op, rs->sr_entry,
			slap_schema.si_ad_objectClass,
			&oc->soc_cname, ACL_READ, &acl_state ) )
		{
			continue;
		}

		aa_add_oc( oc, &ocp, &atp );

		if ( oc->soc_sups ) {
			int i;

			for ( i = 0; oc->soc_sups[ i ] != NULL; i++ ) {
				aa_add_oc( oc->soc_sups[ i ], &ocp, &atp );
			}
		}
	}

	ch_free( ocp );

	if ( atp != NULL ) {
		BerVarray	bv_allowed = NULL,
				bv_effective = NULL;
		int		i, ja = 0, je = 0;

		for ( i = 0; atp[ i ] != NULL; i++ )
			/* just count */ ;
	
		if ( got & GOT_A ) {
			bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}
		if ( got & GOT_AE ) {
			bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}

		for ( i = 0, ja = 0, je = 0; atp[ i ] != NULL; i++ ) {
			if ( got & GOT_A ) {
				ber_dupbv( &bv_allowed[ ja ], &atp[ i ]->sat_cname );
				ja++;
			}

			if ( got & GOT_AE ) {
				AttributeDescription	*ad = NULL;
				const char		*text = NULL;
	
				if ( slap_bv2ad( &atp[ i ]->sat_cname, &ad, &text ) ) {
					/* log? */
					continue;
				}

				if ( access_allowed( op, rs->sr_entry,
					ad, NULL, ACL_WRITE, NULL ) )
				{
					ber_dupbv( &bv_effective[ je ], &atp[ i ]->sat_cname );
					je++;
				}
			}
		}

		ch_free( atp );

		if ( ( got & GOT_A ) && ja > 0 ) {
			BER_BVZERO( &bv_allowed[ ja ] );
			*ap = attr_alloc( ad_allowedAttributes );
			(*ap)->a_vals = bv_allowed;
			(*ap)->a_nvals = bv_allowed;
			(*ap)->a_numvals = ja;
			ap = &(*ap)->a_next;
		}

		if ( ( got & GOT_AE ) && je > 0 ) {
			BER_BVZERO( &bv_effective[ je ] );
			*ap = attr_alloc( ad_allowedAttributesEffective );
			(*ap)->a_vals = bv_effective;
			(*ap)->a_nvals = bv_effective;
			(*ap)->a_numvals = je;
			ap = &(*ap)->a_next;
		}

		*ap = NULL;
	}

do_oc:;
	if ( ( got & GOT_C ) || ( got & GOT_CE ) ) {
		BerVarray	bv_allowed = NULL,
				bv_effective = NULL;
		int		i, ja = 0, je = 0;

		ObjectClass	*oc;

		for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) {
			/* we can only add AUXILIARY objectClasses */
			if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
				continue;
			}

			i++;
		}

		if ( got & GOT_C ) {
			bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}
		if ( got & GOT_CE ) {
			bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
		}

		for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) {
			/* we can only add AUXILIARY objectClasses */
			if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
				continue;
			}

			if ( got & GOT_C ) {
				ber_dupbv( &bv_allowed[ ja ], &oc->soc_cname );
				ja++;
			}

			if ( got & GOT_CE ) {
				if ( !access_allowed( op, rs->sr_entry,
					slap_schema.si_ad_objectClass,
					&oc->soc_cname, ACL_WRITE, NULL ) )
				{
					goto done_ce;
				}

				if ( oc->soc_required ) {
					for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) {
						AttributeDescription	*ad = NULL;
						const char		*text = NULL;
	
						if ( slap_bv2ad( &oc->soc_required[ i ]->sat_cname, &ad, &text ) ) {
							/* log? */
							continue;
						}

						if ( !access_allowed( op, rs->sr_entry,
							ad, NULL, ACL_WRITE, NULL ) )
						{
							goto done_ce;
						}
					}
				}

				ber_dupbv( &bv_effective[ je ], &oc->soc_cname );
				je++;
			}
done_ce:;
		}

		if ( ( got & GOT_C ) && ja > 0 ) {
			BER_BVZERO( &bv_allowed[ ja ] );
			*ap = attr_alloc( ad_allowedChildClasses );
			(*ap)->a_vals = bv_allowed;
			(*ap)->a_nvals = bv_allowed;
			(*ap)->a_numvals = ja;
			ap = &(*ap)->a_next;
		}

		if ( ( got & GOT_CE ) && je > 0 ) {
			BER_BVZERO( &bv_effective[ je ] );
			*ap = attr_alloc( ad_allowedChildClassesEffective );
			(*ap)->a_vals = bv_effective;
			(*ap)->a_nvals = bv_effective;
			(*ap)->a_numvals = je;
			ap = &(*ap)->a_next;
		}

		*ap = NULL;
	}

	return SLAP_CB_CONTINUE;
}
Ejemplo n.º 27
0
static int
ldap_build_entry(
		Operation	*op,
		LDAPMessage	*e,
		Entry		*ent,
		struct berval	*bdn )
{
	struct berval	a;
	BerElement	ber = *ldap_get_message_ber( e );
	Attribute	*attr, **attrp;
	const char	*text;
	int		last;
	char *lastb;
	ber_len_t len;

	/* safe assumptions ... */
	assert( ent != NULL );
	BER_BVZERO( &ent->e_bv );

	if ( ber_scanf( &ber, "{m", bdn ) == LBER_ERROR ) {
		return LDAP_DECODING_ERROR;
	}

	/*
	 * Note: this may fail if the target host(s) schema differs
	 * from the one known to the meta, and a DN with unknown
	 * attributes is returned.
	 * 
	 * FIXME: should we log anything, or delegate to dnNormalize?
	 */
	/* Note: if the distinguished values or the naming attributes
	 * change, should we massage them as well?
	 */
	if ( dnPrettyNormal( NULL, bdn, &ent->e_name, &ent->e_nname,
		op->o_tmpmemctx ) != LDAP_SUCCESS )
	{
		return LDAP_INVALID_DN_SYNTAX;
	}

	ent->e_attrs = NULL;
	if ( ber_first_element( &ber, &len, &lastb ) != LBER_SEQUENCE ) {
		return LDAP_SUCCESS;
	}

	attrp = &ent->e_attrs;
	while ( ber_next_element( &ber, &len, lastb ) == LBER_SEQUENCE &&
		ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
		int				i;
		slap_syntax_validate_func	*validate;
		slap_syntax_transform_func	*pretty;

		attr = attr_alloc( NULL );
		if ( attr == NULL ) {
			return LDAP_OTHER;
		}
		if ( slap_bv2ad( &a, &attr->a_desc, &text ) 
				!= LDAP_SUCCESS )
		{
			if ( slap_bv2undef_ad( &a, &attr->a_desc, &text,
				SLAP_AD_PROXIED ) != LDAP_SUCCESS )
			{
				Debug( LDAP_DEBUG_ANY, 
					"%s ldap_build_entry: "
					"slap_bv2undef_ad(%s): %s\n",
					op->o_log_prefix, a.bv_val, text );

				( void )ber_scanf( &ber, "x" /* [W] */ );
				attr_free( attr );
				continue;
			}
		}

		/* no subschemaSubentry */
		if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
			|| attr->a_desc == slap_schema.si_ad_entryDN )
		{

			/* 
			 * We eat target's subschemaSubentry because
			 * a search for this value is likely not
			 * to resolve to the appropriate backend;
			 * later, the local subschemaSubentry is
			 * added.
			 *
			 * We also eat entryDN because the frontend
			 * will reattach it without checking if already
			 * present...
			 */
			( void )ber_scanf( &ber, "x" /* [W] */ );
			attr_free( attr );
			continue;
		}
		
		if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
				|| attr->a_vals == NULL )
		{
			/*
			 * Note: attr->a_vals can be null when using
			 * values result filter
			 */
			attr->a_vals = (struct berval *)&slap_dummy_bv;
		}

		validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
		pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;

		if ( !validate && !pretty ) {
			attr->a_nvals = NULL;
			attr_free( attr );
			goto next_attr;
		}

		for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) ;
		last = i;

		/*
		 * check that each value is valid per syntax
		 * and pretty if appropriate
		 */
		for ( i = 0; i<last; i++ ) {
			struct berval	pval;
			int		rc;

			if ( pretty ) {
				rc = ordered_value_pretty( attr->a_desc,
					&attr->a_vals[i], &pval, NULL );

			} else {
				rc = ordered_value_validate( attr->a_desc,
					&attr->a_vals[i], 0 );
			}

			if ( rc != LDAP_SUCCESS ) {
				ObjectClass *oc;

				/* check if, by chance, it's an undefined objectClass */
				if ( attr->a_desc == slap_schema.si_ad_objectClass &&
						( oc = oc_bvfind_undef( &attr->a_vals[i] ) ) != NULL )
				{
					ber_dupbv( &pval, &oc->soc_cname );
					rc = LDAP_SUCCESS;

				} else {
					ber_memfree( attr->a_vals[i].bv_val );
					if ( --last == i ) {
						BER_BVZERO( &attr->a_vals[i] );
						break;
					}
					attr->a_vals[i] = attr->a_vals[last];
					BER_BVZERO( &attr->a_vals[last] );
					i--;
				}
			}

			if ( rc == LDAP_SUCCESS && pretty ) {
				ber_memfree( attr->a_vals[i].bv_val );
				attr->a_vals[i] = pval;
			}
		}
		attr->a_numvals = last = i;
		if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
			attr->a_nvals = NULL;
			attr_free( attr );
			goto next_attr;
		}

		if ( last && attr->a_desc->ad_type->sat_equality &&
				attr->a_desc->ad_type->sat_equality->smr_normalize )
		{
			attr->a_nvals = ch_malloc( ( last + 1 )*sizeof( struct berval ) );
			for ( i = 0; i < last; i++ ) {
				int		rc;

				rc = ordered_value_normalize(
					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
					attr->a_desc,
					attr->a_desc->ad_type->sat_equality,
					&attr->a_vals[i], &attr->a_nvals[i],
					NULL );

				if ( rc != LDAP_SUCCESS ) {
					ber_memfree( attr->a_vals[i].bv_val );
					if ( --last == i ) {
						BER_BVZERO( &attr->a_vals[i] );
						break;
					}
					attr->a_vals[i] = attr->a_vals[last];
					BER_BVZERO( &attr->a_vals[last] );
					i--;
				}
			}
			BER_BVZERO( &attr->a_nvals[i] );
			if ( last == 0 ) {
				attr_free( attr );
				goto next_attr;
			}

		} else {
			attr->a_nvals = attr->a_vals;
		}

		attr->a_numvals = last;

		/* Handle sorted vals, strip dups but keep the attr */
		if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
			while ( attr->a_numvals > 1 ) {
				int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx );
				if ( rc != LDAP_TYPE_OR_VALUE_EXISTS )
					break;

				/* Strip duplicate values */
				if ( attr->a_nvals != attr->a_vals )
					ber_memfree( attr->a_nvals[i].bv_val );
				ber_memfree( attr->a_vals[i].bv_val );
				attr->a_numvals--;

				assert( i >= 0 );
				if ( (unsigned)i < attr->a_numvals ) {
					attr->a_vals[i] = attr->a_vals[attr->a_numvals];
					if ( attr->a_nvals != attr->a_vals )
						attr->a_nvals[i] = attr->a_nvals[attr->a_numvals];
				}
				BER_BVZERO(&attr->a_vals[attr->a_numvals]);
				if ( attr->a_nvals != attr->a_vals )
					BER_BVZERO(&attr->a_nvals[attr->a_numvals]);
			}
			attr->a_flags |= SLAP_ATTR_SORTED_VALS;
		}

		*attrp = attr;
		attrp = &attr->a_next;

next_attr:;
	}

	return LDAP_SUCCESS;
}
Ejemplo n.º 28
0
int
slap_send_search_reference( Operation *op, SlapReply *rs )
{
	BerElementBuffer berbuf;
	BerElement	*ber = (BerElement *) &berbuf;
	int rc = 0;
	int bytes;
	char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)";

	AttributeDescription *ad_ref = slap_schema.si_ad_ref;
	AttributeDescription *ad_entry = slap_schema.si_ad_entry;

	rs->sr_type = REP_SEARCHREF;
	if ( op->o_callback ) {
		rc = slap_response_play( op, rs );
		if ( rc != SLAP_CB_CONTINUE ) {
			goto rel;
		}
	}

	Debug( LDAP_DEBUG_TRACE,
		"=> send_search_reference: dn=\"%s\"\n",
		edn, 0, 0 );

	if (  rs->sr_entry && ! access_allowed( op, rs->sr_entry,
		ad_entry, NULL, ACL_READ, NULL ) )
	{
		Debug( LDAP_DEBUG_ACL,
			"send_search_reference: access to entry not allowed\n",
		    0, 0, 0 );
		rc = 1;
		goto rel;
	}

	if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
		ad_ref, NULL, ACL_READ, NULL ) )
	{
		Debug( LDAP_DEBUG_ACL,
			"send_search_reference: access "
			"to reference not allowed\n",
		    0, 0, 0 );
		rc = 1;
		goto rel;
	}

	if( op->o_domain_scope ) {
		Debug( LDAP_DEBUG_ANY,
			"send_search_reference: domainScope control in (%s)\n", 
			edn, 0, 0 );
		rc = 0;
		goto rel;
	}

	if( rs->sr_ref == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"send_search_reference: null ref in (%s)\n", 
			edn, 0, 0 );
		rc = 1;
		goto rel;
	}

	if( op->o_protocol < LDAP_VERSION3 ) {
		rc = 0;
		/* save the references for the result */
		if( rs->sr_ref[0].bv_val != NULL ) {
			if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
				rc = LDAP_OTHER;
		}
		goto rel;
	}

#ifdef LDAP_CONNECTIONLESS
	if( op->o_conn && op->o_conn->c_is_udp ) {
		ber = op->o_res_ber;
	} else
#endif
	{
		ber_init_w_nullc( ber, LBER_USE_DER );
		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
	}

	rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
		LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );

	if( rc != -1 ) {
		rc = send_ldap_controls( op, ber, rs->sr_ctrls );
	}

	if( rc != -1 ) {
		rc = ber_printf( ber, /*"{"*/ "N}" );
	}

	if ( rc == -1 ) {
		Debug( LDAP_DEBUG_ANY,
			"send_search_reference: ber_printf failed\n", 0, 0, 0 );

#ifdef LDAP_CONNECTIONLESS
		if (!op->o_conn || op->o_conn->c_is_udp == 0)
#endif
		ber_free_buf( ber );
		send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" );
		goto rel;
	}

	rc = 0;
	if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
		assert( rs->sr_entry != NULL );
		be_entry_release_rw( op, rs->sr_entry, 0 );
		rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
		rs->sr_entry = NULL;
	}

#ifdef LDAP_CONNECTIONLESS
	if (!op->o_conn || op->o_conn->c_is_udp == 0) {
#endif
	bytes = send_ldap_ber( op, ber );
	ber_free_buf( ber );

	if ( bytes < 0 ) {
		rc = LDAP_UNAVAILABLE;
	} else {
		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
	}
#ifdef LDAP_CONNECTIONLESS
	}
#endif
	if ( rs->sr_ref != NULL ) {
		int	r;

		for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) {
			Statslog( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n",
				op->o_log_prefix, r, rs->sr_ref[0].bv_val,
				0, 0 );
		}

	} else {
		Statslog( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n",
			op->o_log_prefix, 0, 0, 0, 0 );
	}

	Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );

rel:
	if ( op->o_callback ) {
		(void)slap_cleanup_play( op, rs );
	}

	return rc;
}
Ejemplo n.º 29
0
int
backsql_delete( Operation *op, SlapReply *rs )
{
    SQLHDBC 		dbh = SQL_NULL_HDBC;
    SQLHSTMT		sth = SQL_NULL_HSTMT;
    backsql_oc_map_rec	*oc = NULL;
    backsql_srch_info	bsi = { 0 };
    backsql_entryID		e_id = { 0 };
    Entry			d = { 0 }, p = { 0 }, *e = NULL;
    struct berval		pdn = BER_BVNULL;
    int			manageDSAit = get_manageDSAit( op );

    Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
           op->o_req_ndn.bv_val, 0, 0 );

    rs->sr_err = backsql_get_db_conn( op, &dbh );
    if ( rs->sr_err != LDAP_SUCCESS ) {
        Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
               "could not get connection handle - exiting\n",
               0, 0, 0 );
        rs->sr_text = ( rs->sr_err == LDAP_OTHER )
                      ? "SQL-backend error" : NULL;
        e = NULL;
        goto done;
    }

    /*
     * Get the entry
     */
    bsi.bsi_e = &d;
    rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
                                      LDAP_SCOPE_BASE,
                                      (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
                                      ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
    switch ( rs->sr_err ) {
    case LDAP_SUCCESS:
        break;

    case LDAP_REFERRAL:
        if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
                dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
        {
            rs->sr_err = LDAP_SUCCESS;
            rs->sr_text = NULL;
            rs->sr_matched = NULL;
            if ( rs->sr_ref ) {
                ber_bvarray_free( rs->sr_ref );
                rs->sr_ref = NULL;
            }
            break;
        }
        e = &d;
    /* fallthru */

    default:
        Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
               "could not retrieve deleteDN ID - no such entry\n",
               0, 0, 0 );
        if ( !BER_BVISNULL( &d.e_nname ) ) {
            /* FIXME: should always be true! */
            e = &d;

        } else {
            e = NULL;
        }
        goto done;
    }

    if ( get_assert( op ) &&
            ( test_filter( op, &d, get_assertion( op ) )
              != LDAP_COMPARE_TRUE ) )
    {
        rs->sr_err = LDAP_ASSERTION_FAILED;
        e = &d;
        goto done;
    }

    if ( !access_allowed( op, &d, slap_schema.si_ad_entry,
                          NULL, ACL_WDEL, NULL ) )
    {
        Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
               "no write access to entry\n",
               0, 0, 0 );
        rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
        e = &d;
        goto done;
    }

    rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn );
    switch ( rs->sr_err ) {
    case LDAP_COMPARE_FALSE:
        rs->sr_err = LDAP_SUCCESS;
        break;

    case LDAP_COMPARE_TRUE:
#ifdef SLAP_CONTROL_X_TREE_DELETE
        if ( get_treeDelete( op ) ) {
            rs->sr_err = LDAP_SUCCESS;
            break;
        }
#endif /* SLAP_CONTROL_X_TREE_DELETE */

        Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
               "entry \"%s\" has children\n",
               op->o_req_dn.bv_val, 0, 0 );
        rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
        rs->sr_text = "subordinate objects must be deleted first";
    /* fallthru */

    default:
        e = &d;
        goto done;
    }

    assert( bsi.bsi_base_id.eid_oc != NULL );
    oc = bsi.bsi_base_id.eid_oc;
    if ( oc->bom_delete_proc == NULL ) {
        Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
               "delete procedure is not defined "
               "for this objectclass - aborting\n", 0, 0, 0 );
        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
        rs->sr_text = "operation not permitted within namingContext";
        e = NULL;
        goto done;
    }

    /*
     * Get the parent
     */
    e_id = bsi.bsi_base_id;
    memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
    if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
        dnParent( &op->o_req_ndn, &pdn );
        bsi.bsi_e = &p;
        rs->sr_err = backsql_init_search( &bsi, &pdn,
                                          LDAP_SCOPE_BASE,
                                          (time_t)(-1), NULL, dbh, op, rs,
                                          slap_anlist_no_attrs,
                                          BACKSQL_ISF_GET_ENTRY );
        if ( rs->sr_err != LDAP_SUCCESS ) {
            Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
                   "could not retrieve deleteDN ID "
                   "- no such entry\n",
                   0, 0, 0 );
            e = &p;
            goto done;
        }

        (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );

        /* check parent for "children" acl */
        if ( !access_allowed( op, &p, slap_schema.si_ad_children,
                              NULL, ACL_WDEL, NULL ) )
        {
            Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
                   "no write access to parent\n",
                   0, 0, 0 );
            rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
            e = &p;
            goto done;

        }
    }

    e = &d;
#ifdef SLAP_CONTROL_X_TREE_DELETE
    if ( get_treeDelete( op ) ) {
        backsql_tree_delete( op, rs, dbh, &sth );
        if ( rs->sr_err == LDAP_OTHER || rs->sr_err == LDAP_SUCCESS )
        {
            e = NULL;
        }

    } else
#endif /* SLAP_CONTROL_X_TREE_DELETE */
    {
        backsql_delete_int( op, rs, dbh, &sth, &e_id, &e );
    }

    /*
     * Commit only if all operations succeed
     */
    if ( sth != SQL_NULL_HSTMT ) {
        SQLUSMALLINT	CompletionType = SQL_ROLLBACK;

        if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
            assert( e == NULL );
            CompletionType = SQL_COMMIT;
        }

        SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
    }

done:
    ;
    if ( e != NULL ) {
        if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
                              ACL_DISCLOSE, NULL ) )
        {
            rs->sr_err = LDAP_NO_SUCH_OBJECT;
            rs->sr_text = NULL;
            rs->sr_matched = NULL;
            if ( rs->sr_ref ) {
                ber_bvarray_free( rs->sr_ref );
                rs->sr_ref = NULL;
            }
        }
    }

    if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
        rs->sr_err = LDAP_X_NO_OPERATION;
    }

    send_ldap_result( op, rs );

    Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );

    if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
        (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
    }

    if ( !BER_BVISNULL( &d.e_nname ) ) {
        backsql_entry_clean( op, &d );
    }

    if ( !BER_BVISNULL( &p.e_nname ) ) {
        backsql_entry_clean( op, &p );
    }

    if ( rs->sr_ref ) {
        ber_bvarray_free( rs->sr_ref );
        rs->sr_ref = NULL;
    }

    return rs->sr_err;
}
Ejemplo n.º 30
0
static int
nss_cf_gen(ConfigArgs *c)
{
	slap_overinst *on = (slap_overinst *)c->bi;
	nssov_info *ni = on->on_bi.bi_private;
	nssov_mapinfo *mi;
	int i, j, rc = 0;
	slap_mask_t m;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		switch(c->type) {
		case NSS_SSD:
			rc = 1;
			for (i=NM_alias;i<NM_NONE;i++) {
				struct berval scope;
				struct berval ssd;
				struct berval base;

				mi = &ni->ni_maps[i];

				/* ignore all-default services */
				if ( mi->mi_scope == LDAP_SCOPE_DEFAULT &&
					bvmatch( &mi->mi_filter, &mi->mi_filter0 ) &&
					BER_BVISNULL( &mi->mi_base ))
					continue;

				if ( BER_BVISNULL( &mi->mi_base ))
					base = ni->ni_db->be_nsuffix[0];
				else
					base = mi->mi_base;
				ldap_pvt_scope2bv(mi->mi_scope == LDAP_SCOPE_DEFAULT ?
					LDAP_SCOPE_SUBTREE : mi->mi_scope, &scope);
				ssd.bv_len = STRLENOF(" ldap:///???") + nss_svcs[i].word.bv_len +
					base.bv_len + scope.bv_len + mi->mi_filter.bv_len;
				ssd.bv_val = ch_malloc( ssd.bv_len + 1 );
				sprintf(ssd.bv_val, "%s ldap:///%s??%s?%s", nss_svcs[i].word.bv_val,
					base.bv_val, scope.bv_val, mi->mi_filter.bv_val );
				ber_bvarray_add( &c->rvalue_vals, &ssd );
				rc = 0;
			}
			break;
		case NSS_MAP:
			rc = 1;
			for (i=NM_alias;i<NM_NONE;i++) {

				mi = &ni->ni_maps[i];
				for (j=0;!BER_BVISNULL(&mi->mi_attrkeys[j]);j++) {
					if ( ber_bvstrcasecmp(&mi->mi_attrkeys[j],
						&mi->mi_attrs[j].an_name)) {
						struct berval map;

						map.bv_len = nss_svcs[i].word.bv_len +
							mi->mi_attrkeys[j].bv_len +
							mi->mi_attrs[j].an_desc->ad_cname.bv_len + 2;
						map.bv_val = ch_malloc(map.bv_len + 1);
						sprintf(map.bv_val, "%s %s %s", nss_svcs[i].word.bv_val,
							mi->mi_attrkeys[j].bv_val, mi->mi_attrs[j].an_desc->ad_cname.bv_val );
						ber_bvarray_add( &c->rvalue_vals, &map );
						rc = 0;
					}
				}
			}
			break;
		case NSS_PAM:
			rc = mask_to_verbs( pam_opts, ni->ni_pam_opts, &c->rvalue_vals );
			break;
		case NSS_PAMGROUP:
			if (!BER_BVISEMPTY( &ni->ni_pam_group_dn )) {
				value_add_one( &c->rvalue_vals, &ni->ni_pam_group_dn );
				value_add_one( &c->rvalue_nvals, &ni->ni_pam_group_dn );
			} else {
				rc = 1;
			}
			break;
		case NSS_PAMSESS:
			if (ni->ni_pam_sessions) {
				ber_bvarray_dup_x( &c->rvalue_vals, ni->ni_pam_sessions, NULL );
			} else {
				rc = 1;
			}
			break;
		}
		return rc;
	} else if ( c->op == LDAP_MOD_DELETE ) {
		/* FIXME */
		return 1;
	}
	switch( c->type ) {
	case NSS_SSD: {
		LDAPURLDesc *lud;

		i = verb_to_mask(c->argv[1], nss_svcs);
		if ( i == NM_NONE )
			return 1;

		mi = &ni->ni_maps[i];
		rc = ldap_url_parse(c->argv[2], &lud);
		if ( rc )
			return 1;
		do {
			struct berval base;
			/* Must be LDAP scheme */
			if (strcasecmp(lud->lud_scheme,"ldap")) {
				rc = 1;
				break;
			}
			/* Host part, attrs, and extensions must be empty */
			if (( lud->lud_host && *lud->lud_host ) ||
				lud->lud_attrs || lud->lud_exts ) {
				rc = 1;
				break;
			}
			ber_str2bv( lud->lud_dn,0,0,&base);
			rc = dnNormalize( 0,NULL,NULL,&base,&mi->mi_base,NULL);
			if ( rc )
				break;
			if ( lud->lud_filter ) {
				/* steal this */
				ber_str2bv( lud->lud_filter,0,0,&mi->mi_filter);
				lud->lud_filter = NULL;
			}
			mi->mi_scope = lud->lud_scope;
		} while(0);
		ldap_free_urldesc( lud );
		}
		break;
	case NSS_MAP:
		i = verb_to_mask(c->argv[1], nss_svcs);
		if ( i == NM_NONE )
			return 1;
		rc = 1;
		mi = &ni->ni_maps[i];
		for (j=0; !BER_BVISNULL(&mi->mi_attrkeys[j]); j++) {
			if (!strcasecmp(c->argv[2],mi->mi_attrkeys[j].bv_val)) {
				AttributeDescription *ad = NULL;
				const char *text;
				rc = slap_str2ad( c->argv[3], &ad, &text);
				if ( rc == 0 ) {
					mi->mi_attrs[j].an_desc = ad;
					mi->mi_attrs[j].an_name = ad->ad_cname;
				}
				break;
			}
		}
		break;
	case NSS_PAM:
		m = ni->ni_pam_opts;
		i = verbs_to_mask(c->argc, c->argv, pam_opts, &m);
		if (i == 0) {
			ni->ni_pam_opts = m;
			if ((m & NI_PAM_USERHOST) && !nssov_pam_host_ad) {
				const char *text;
				i = slap_str2ad("host", &nssov_pam_host_ad, &text);
				if (i != LDAP_SUCCESS) {
					snprintf(c->cr_msg, sizeof(c->cr_msg),
						"nssov: host attr unknown: %s", text);
					Debug(LDAP_DEBUG_ANY,"%s\n",c->cr_msg,0,0);
					rc = 1;
					break;
				}
			}
			if ((m & (NI_PAM_USERSVC|NI_PAM_HOSTSVC)) && !nssov_pam_svc_ad) {
				const char *text;
				i = slap_str2ad("authorizedService", &nssov_pam_svc_ad, &text);
				if (i != LDAP_SUCCESS) {
					snprintf(c->cr_msg, sizeof(c->cr_msg),
						"nssov: authorizedService attr unknown: %s", text);
					Debug(LDAP_DEBUG_ANY,"%s\n",c->cr_msg,0,0);
					rc = 1;
					break;
				}
			}
		} else {
			rc = 1;
		}
		break;
	case NSS_PAMGROUP:
		ni->ni_pam_group_dn = c->value_ndn;
		ch_free( c->value_dn.bv_val );
		break;
	case NSS_PAMSESS:
		ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
		ber_bvarray_add( &ni->ni_pam_sessions, &c->value_bv );
		break;
	}
	return rc;
}