示例#1
0
文件: compare.c 项目: leto/389-ds
/*
 *  Function: ldif_back_compare
 *
 *  Returns: -1, 0 or 1 
 *  
 *  Description: compares entries in the ldif backend
 */
int
ldif_back_compare( Slapi_PBlock *pb )
{
  LDIF          *db;         /*The Database*/
  ldif_Entry    *e, *prev;   /*Used for searching the database*/
  char          *dn, *type;  /*The dn and the type*/
  struct berval *bval;
  Slapi_Attr	*attr;
  int rc;

  LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_compare\n", 0, 0, 0 );
  prev = NULL;

  if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
      slapi_pblock_get( pb, SLAPI_COMPARE_TARGET, &dn ) < 0 ||
      slapi_pblock_get( pb, SLAPI_COMPARE_TYPE, &type ) < 0 ||
      slapi_pblock_get( pb, SLAPI_COMPARE_VALUE, &bval ) < 0){
    slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
    return(-1);
  }
  
  /*Lock the database*/
  PR_Lock( db->ldif_lock );

  
  /*Find the entry for comparison*/
  if ( (e = (ldif_Entry*) ldif_find_entry( pb, db, dn, &prev )) == NULL ) {
    slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
    PR_Unlock( db->ldif_lock );
    return( 1 );
  }
  
  /*Check the access*/
  rc= slapi_access_allowed( pb, e->lde_e, type, bval, SLAPI_ACL_COMPARE );
  if ( rc!=LDAP_SUCCESS  ) {
    slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL );
    PR_Unlock( db->ldif_lock );
    return( 1 );
  }
  
  /*find the attribute*/
  if ( slapi_entry_attr_find( e->lde_e, type, &attr ) != 0 ) {
    slapi_send_ldap_result( pb, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL, 0, NULL );
    PR_Unlock( db->ldif_lock );
    return( 1 );
  }
  
  if ( slapi_attr_value_find( attr, bval ) == 0 ) {
    slapi_send_ldap_result( pb, LDAP_COMPARE_TRUE, NULL, NULL, 0, NULL );
    PR_Unlock( db->ldif_lock );
    return( 0 );
  }
  
  slapi_send_ldap_result( pb, LDAP_COMPARE_FALSE, NULL, NULL, 0, NULL );
  PR_Unlock( db->ldif_lock );
  LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_compare\n", 0, 0, 0 );
  return( 0 );
}
示例#2
0
文件: delete.c 项目: leto/389-ds
/* 	This is new style API to issue internal delete operation.
	pblock should contain the following data (can be set via call to slapi_delete_internal_set_pb):
	For uniqueid based operation:
		SLAPI_TARGET_DN set to dn that allows to select right backend, can be stale
		SLAPI_TARGET_UNIQUEID set to the uniqueid of the entry we are looking for
		SLAPI_CONTROLS_ARG set to request controls if present

	For dn based search:
		SLAPI_TARGET_DN set to the entry dn
		SLAPI_CONTROLS_ARG set to request controls if present		 				
 */
int slapi_delete_internal_pb (Slapi_PBlock *pb)
{
	if (pb == NULL)
		return -1;

	if (!allow_operation (pb))
	{
		slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
						 "This plugin is not configured to access operation target data", 0, NULL );
		return 0;
	}

	return delete_internal_pb (pb);
}
示例#3
0
文件: add.c 项目: Firstyear/ds
/*  This is new style API to issue internal add operation.
	pblock should contain the following data (can be set via call to slapi_add_internal_set_pb):
	SLAPI_TARGET_SDN	set to sdn of the new entry
	SLAPI_CONTROLS_ARG	set to request controls if present
	SLAPI_ADD_ENTRY		set to Slapi_Entry to add
	Beware: The entry is consumed. */
int slapi_add_internal_pb (Slapi_PBlock *pb)
{
	if (pb == NULL)
		return -1;

	if (!allow_operation (pb))
	{
		/* free the entry as it's expected to be consumed */
		Slapi_Entry *e;
		slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
		slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
		slapi_entry_free(e);

		slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
						 "This plugin is not configured to access operation target data", 0, NULL );
		return 0;
	}

	return add_internal_pb (pb);
}
示例#4
0
static int addrdnvalues_preop_add(Slapi_PBlock *pb)
{
	int rc;
	Slapi_Entry *e;

	if (slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e) != 0) {
		slapi_log_error(SLAPI_LOG_PLUGIN, "addrdnvalues_preop_add",
				"Error retrieving target entry\n");
		return -1;
	}

	rc = slapi_entry_add_rdn_values(e);
	if (rc != LDAP_SUCCESS) {
		slapi_send_ldap_result(pb, LDAP_OTHER, NULL,
			"Failed to parse distinguished name", 0, NULL);
		slapi_log_error(SLAPI_LOG_PLUGIN, "addrdnvalues_preop_add",
			"Failed to parse distinguished name: %s\n",
			ldap_err2string(rc));
		return -1;
	}

	return 0;
}
示例#5
0
int oath_preop_bind(Slapi_PBlock *pb) {

    char *dn;
    const char *creds;
    int creds_len, hotp_len = oath_preop_config.hotp_length, pin_len, method, rc = LDAP_SUCCESS, handled = 1;
    struct berval *credentials;
    Slapi_Value *sv_creds = NULL;
    Slapi_PBlock *upb, *tpb; // PBlocks for user and token searches
    Token token;

    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind\n");

    if (slapi_pblock_get(pb, SLAPI_BIND_METHOD, (void *) &method) != 0 ||
            slapi_pblock_get(pb, SLAPI_BIND_TARGET, (void *) &dn) != 0 ||
            slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, (void *) &credentials) != 0) {
        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Could not get parameters for bind operation\n");
        slapi_send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
        return 1;
    }

    switch (method) {

    case LDAP_AUTH_SIMPLE:

        rc = LDAP_SUCCESS;
        sv_creds = slapi_value_new_berval(credentials);
        creds = slapi_value_get_string(sv_creds);
        creds_len = creds ? strlen(creds) : 0;

        Slapi_Entry **entries, *entry;
        int nentries = 0;

        upb = slapi_pblock_new();
        slapi_search_internal_set_pb(upb, dn, LDAP_SCOPE_SUB, "(objectClass=*)", NULL, 0, NULL, NULL, oath_preop_plugin_id, 0);
        slapi_search_internal_pb(upb);
        slapi_pblock_get(upb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
        slapi_pblock_get(upb, SLAPI_NENTRIES, &nentries);
        slapi_pblock_get(upb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);

        if (rc == LDAP_SUCCESS && nentries > 0 && entries != NULL && (entry = *entries) != NULL) {

            char filter[1024], *attrs[] = {"tokenSerial", "tokenSeed", "tokenCounter", "tokenPIN", NULL};
            Slapi_Entry **tokens;
            int ntokens = 0;

            slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Authenticating DN: %s\n", dn);

            // search for tokens

            snprintf(filter, 1024, "(&(objectClass=oathToken)(tokenOwner=%s))", dn);

            tpb = slapi_pblock_new();
            slapi_search_internal_set_pb(tpb, oath_preop_config.token_base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, oath_preop_plugin_id, 0);
            slapi_search_internal_pb(tpb);
            slapi_pblock_get(tpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
            slapi_pblock_get(tpb, SLAPI_NENTRIES, &ntokens);
            slapi_pblock_get(tpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &tokens);

            if (rc == LDAP_SUCCESS && ntokens > 0 && tokens != NULL) {

                int t, w;
                unsigned char hotp[hotp_len + 1];

                for (t = 0; t < ntokens; t++) {

                    oath_token_from_entry(&token, tokens[t]);

                    pin_len = token.pin ? strlen(token.pin) : 0;

                    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Found token: %s\n", token.serial);

                    if (pin_len + hotp_len != creds_len)
                        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Credentials length did not match\n");

                    else if (token.pin && strncmp(creds, token.pin, pin_len))
                        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: PIN did not match\n");

                    else for (w = 0; w < oath_preop_config.hotp_inner_window; w++) {

                            if (oath_hotp(hotp, hotp_len, token.seed->bv_val, token.seed->bv_len, token.counter + w, oath_preop_config.hotp_trunc_offset, oath_preop_config.hotp_checksum)) {

                                // slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: hotp(%d) =  %s\n", token.counter + w, hotp);

                                if (!strncmp(hotp, creds + pin_len, hotp_len)) {

                                    // success
                                    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: hotp(%d) =  %s\n", token.counter + w, hotp);

                                    if (oath_update_token(tokens[t], token.counter + w + 1) != 0) {
                                        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Failed to update token entry\n");
                                        rc = LDAP_OPERATIONS_ERROR;
                                    };

                                    // OpenLDAP does not support setting SLAPI_CONN_DN and SLAPI_CONN_AUTHMETHOD

                                    /*
                                                                        if (slapi_pblock_set(pb, SLAPI_CONN_DN, slapi_ch_strdup(dn)) != 0 ||
                                                                                slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD, SLAPD_AUTH_SIMPLE) != 0) {
                                                                            slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Failed to set DN and auth method for connection\n", dn);
                                                                            rc = LDAP_OPERATIONS_ERROR;
                                                                        }
                                    */

                                    goto free_tpb;

                                }

                            } else {
                                // HOTP error
                                slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: HOTP error for token %s\n", token.serial);
                                break;
                            }

                        }

                    slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: Token %s did not match\n", token.serial);
                    oath_token_free(&token);

                }

                // No token matched

                handled = 0;
                goto free_tpb;

            } else { // no tokens associated

                slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: DN %s has got no token(s) associated, rc = %d\n", dn, rc);
                handled = 0;
                goto free_upb;

            }


        } else {

            // entry not found; don't fail because this can be root (directory manager) DN

            slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_preop_bind: DN %s not found\n", dn);

            if (rc == LDAP_SUCCESS)
                rc = LDAP_OPERATIONS_ERROR;
            else
                handled = 0;

            goto free_upb;

        }

        break;

    case LDAP_AUTH_NONE:
    case LDAP_AUTH_SASL:
    default:
        slapi_log_error(SLAPI_LOG_PLUGIN, "oath", "oath_bind_preop: Authentication type not supported: %d", method);
        return 0;

    }

free_tpb:
    oath_token_free(&token);
    slapi_free_search_results_internal(tpb);
    slapi_pblock_destroy(tpb);

free_upb:
    slapi_free_search_results_internal(upb);
    slapi_pblock_destroy(upb);

    slapi_value_free(&sv_creds);

    if (handled) {
        slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL);
        return 1;
    } else
        return 0;

}
示例#6
0
文件: ldbm_bind.c 项目: leto/389-ds
int
ldbm_back_bind( Slapi_PBlock *pb )
{
	backend *be;
	ldbm_instance *inst;
	int			method;
	struct berval		*cred;
	struct ldbminfo		*li;
	struct backentry	*e;
	Slapi_Attr		*attr;
	Slapi_Value **bvals;
	entry_address *addr;
	back_txn txn = {NULL};

	/* get parameters */
	slapi_pblock_get( pb, SLAPI_BACKEND, &be );
	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
	slapi_pblock_get( pb, SLAPI_TARGET_ADDRESS, &addr );
	slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method );
	slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &cred );
	slapi_pblock_get( pb, SLAPI_TXN, &txn.back_txn_txn );

	if ( !txn.back_txn_txn ) {
		dblayer_txn_init( li, &txn );
		slapi_pblock_set( pb, SLAPI_TXN, txn.back_txn_txn );
	}
	
	inst = (ldbm_instance *) be->be_instance_info;

	/* always allow noauth simple binds (front end will send the result) */
	if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
		return( SLAPI_BIND_ANONYMOUS );
	}

	/*
	 * find the target entry.  find_entry() takes care of referrals
	 *   and sending errors if the entry does not exist.
	 */
	if (( e = find_entry( pb, be, addr, &txn )) == NULL ) {
		return( SLAPI_BIND_FAIL );
	}

	switch ( method ) {
	case LDAP_AUTH_SIMPLE:
		{
		Slapi_Value cv;
		if ( slapi_entry_attr_find( e->ep_entry, "userpassword", &attr ) != 0 ) {
#if defined( XP_WIN32 )
			if( WindowsAuthentication( e, cred ) == LDAPWA_Success ) {
				break;
			}
#endif
			slapi_send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
			    NULL, 0, NULL );
			CACHE_RETURN( &inst->inst_cache, &e );
			return( SLAPI_BIND_FAIL );
		}
		bvals= attr_get_present_values(attr);
		slapi_value_init_berval(&cv,cred);
		if ( slapi_pw_find_sv( bvals, &cv ) != 0 ) {
#if defined( XP_WIN32 )
			/* One last try - attempt Windows authentication, 
			   if the user has a Windows account. */
			if( WindowsAuthentication( e, cred ) == LDAPWA_Success ) {
				break;
			}
#endif
			slapi_send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL,
			    NULL, 0, NULL );
			CACHE_RETURN( &inst->inst_cache, &e );
			value_done(&cv);
			return( SLAPI_BIND_FAIL );
		}
		value_done(&cv);
		}
		break;

	default:
		slapi_send_ldap_result( pb, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL,
		    "auth method not supported", 0, NULL );
		CACHE_RETURN( &inst->inst_cache, &e );
		return( SLAPI_BIND_FAIL );
	}

	CACHE_RETURN( &inst->inst_cache, &e );

	/* success:  front end will send result */
	return( SLAPI_BIND_SUCCESS );
}
示例#7
0
文件: seq.c 项目: Firstyear/ds
/*
 * Access the database sequentially.
 * There are 4 ways to call this routine.  In each case, the equality index
 * for "attrname" is consulted:
 *  1) If the SLAPI_SEQ_TYPE parameter is SLAPI_SEQ_FIRST, then this routine
 *     will find the smallest key greater than or equal to the SLAPI_SEQ_VAL
 *     parameter, and return all entries that key's IDList.  If SLAPI_SEQ_VAL
 *     is NULL, then the smallest key is retrieved and the associaated
 *     entries are returned.
 *  2) If the SLAPI_SEQ_TYPE parameter is SLAPI_SEQ_NEXT, then this routine
 *     will find the smallest key strictly greater than the SLAPI_SEQ_VAL
 *     parameter, and return all entries that key's IDList.
 *  3) If the SLAPI_SEQ_TYPE parameter is SLAPI_SEQ_PREV, then this routine
 *     will find the greatest key strictly less than the SLAPI_SEQ_VAL
 *     parameter, and return all entries that key's IDList.
 *  4) If the SLAPI_SEQ_TYPE parameter is SLAPI_SEQ_LAST, then this routine 
 *     will find the largest equality key in the index and return all entries
 *     which match that key.  The SLAPI_SEQ_VAL parameter is ignored.
 */
int
ldbm_back_seq( Slapi_PBlock *pb )
{
	backend         *be;
	ldbm_instance   *inst;
	struct ldbminfo *li;
	IDList          *idl = NULL;
	back_txn        txn = {NULL};
	back_txnid parent_txn;
	struct attrinfo	*ai = NULL;
	DB              *db;
	DBC             *dbc = NULL;
	char *attrname, *val;
	int err = LDAP_SUCCESS;
	int return_value = -1;
	int nentries = 0;
	int retry_count = 0;
	int isroot;
	int type;

	/* Decode arguments */
	slapi_pblock_get( pb, SLAPI_BACKEND, &be);
	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
	slapi_pblock_get( pb, SLAPI_SEQ_TYPE, &type );
	slapi_pblock_get( pb, SLAPI_SEQ_ATTRNAME, &attrname );
	slapi_pblock_get( pb, SLAPI_SEQ_VAL, &val );
	slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
	slapi_pblock_get( pb, SLAPI_TXN, (void **)&parent_txn );

	inst = (ldbm_instance *) be->be_instance_info;

	dblayer_txn_init( li, &txn );
	if (!parent_txn) {
		parent_txn = txn.back_txn_txn;
		slapi_pblock_set( pb, SLAPI_TXN, parent_txn );
	}

	/* Validate arguments */
	if ( type != SLAPI_SEQ_FIRST &&
	     type != SLAPI_SEQ_LAST &&
	     type != SLAPI_SEQ_NEXT &&
	     type != SLAPI_SEQ_PREV )
	{
	    slapi_send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
		    "Bad seq access type", 0, NULL );
	    return( -1 );
	}

	/* get a database */

	ainfo_get( be, attrname, &ai );
	slapi_log_err(SLAPI_LOG_ARGS,
	    "ldbm_back_seq", "indextype: %s indexmask: 0x%x seek type: %d\n",
	    ai->ai_type, ai->ai_indexmask, type );
	if ( ! (INDEX_EQUALITY & ai->ai_indexmask) ) {
		slapi_log_err(SLAPI_LOG_TRACE,
		    "ldbm_back_seq", "caller specified un-indexed attribute %s\n",
			   attrname ? attrname : "");
		slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
		    "Unindexed seq access type", 0, NULL );
		return -1;
	}

	if ( (return_value = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) {
		slapi_log_err(SLAPI_LOG_ERR,
		    "ldbm_back_seq", "Could not open index file for attribute %s\n",
		    attrname);
		slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
		return -1;
	}
retry:
	if (txn.back_txn_txn) {
		dblayer_read_txn_begin(be, parent_txn, &txn);
	}
	/* First, get a database cursor */
	return_value = db->cursor(db, txn.back_txn_txn, &dbc, 0);

	if (0 == return_value)
	{
		DBT data = {0};
		DBT key = {0};
		char little_buffer[SEQ_LITTLE_BUFFER_SIZE];
		char *big_buffer = NULL;
		char keystring = EQ_PREFIX;

		/* Set data */
		data.flags = DB_DBT_MALLOC;

		/* Set up key */
		key.flags = DB_DBT_MALLOC;
		if (NULL == val)
		{
			/* this means, goto the first equality key */
			/* seek to key >= "=" */
			key.data = &keystring;
			key.size = 1;
		}
		else
		{
			size_t key_length = strlen(val) + 2;
			if (key_length <= SEQ_LITTLE_BUFFER_SIZE) {
				key.data = &little_buffer;
			} else {
				big_buffer = slapi_ch_malloc(key_length);
				if (NULL == big_buffer) {
					/* memory allocation failure */
					dblayer_release_index_file( be, ai, db );
					return -1;
				}
				key.data = big_buffer;
			}
			key.size = sprintf(key.data,"%c%s",EQ_PREFIX,val);
		}

		/* decide which type of operation we're being asked to do and do the db bit */
		/* The c_get call always mallocs memory for data.data */
		/* The c_get call mallocs memory for key.data, except for DB_SET */
		/* after this, we leave data containing the retrieved IDL, or NULL if we didn't get it */

		switch (type) {
		case SLAPI_SEQ_FIRST:
			/* if (NULL == val) goto the first equality key ( seek to key >= "=" ) */
			/* else goto the first equality key >= val ( seek to key >= "=val"  )*/
			return_value = dbc->c_get(dbc,&key,&data,DB_SET_RANGE);
			break;
		case SLAPI_SEQ_NEXT:
			/* seek to the indicated =value, then seek to the next entry, */
			return_value = dbc->c_get(dbc,&key,&data,DB_SET);
			if (0 == return_value)
			{
				slapi_ch_free(&(data.data));
				return_value = dbc->c_get(dbc,&key,&data,DB_NEXT);
			}
			else
			{
				/* DB_SET doesn't allocate key data.  Make sure we don't try to free it... */
				key.data= NULL;
			}
			break;
		case SLAPI_SEQ_PREV:
			/* seek to the indicated =value, then seek to the previous entry, */
			return_value = dbc->c_get(dbc,&key,&data,DB_SET);
			if (0 == return_value )
			{
				slapi_ch_free(&(data.data));
				return_value = dbc->c_get(dbc,&key,&data,DB_PREV);
			}
			else
			{
				/* DB_SET doesn't allocate key data.  Make sure we don't try to free it... */
				key.data= NULL;
			}
			break;
		case SLAPI_SEQ_LAST:
			/* seek to the first possible key after all the equality keys (">"), then seek back one */
			{
				keystring = EQ_PREFIX + 1;
				key.data = &keystring;
				key.size = 1;
				return_value = dbc->c_get(dbc,&key,&data,DB_SET_RANGE);
				if ((0 == return_value) || (DB_NOTFOUND == return_value)) {
					slapi_ch_free(&(data.data));
					return_value = dbc->c_get(dbc,&key,&data,DB_PREV); 
				}
			}
			break;
		}

		dbc->c_close(dbc);

		if ((0 == return_value) || (DB_NOTFOUND == return_value)) {
			/* Now check that the key we eventually settled on was an equality key ! */
			if (key.data && *((char*)key.data) == EQ_PREFIX) {
				/* Retrieve the idlist for this key */
				key.flags = 0;
				for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) {
					err = NEW_IDL_DEFAULT;
					idl_free(&idl);
					idl = idl_fetch( be, db, &key, parent_txn, ai, &err );
					if(err == DB_LOCK_DEADLOCK) {
						ldbm_nasty("ldbm_back_seq", "deadlock retry", 1600, err);
						if (txn.back_txn_txn) {
							/* just in case */
							slapi_ch_free(&(data.data));
							if ((key.data != little_buffer) && (key.data != &keystring)) {
								slapi_ch_free(&(key.data));
							}
							dblayer_read_txn_abort(be, &txn);
							goto retry;
						} else {
							continue;
						}
					} else {
						break;
					}
				}
			}
		} else {
			if (txn.back_txn_txn) {
				dblayer_read_txn_abort(be, &txn);
			}
			if (DB_LOCK_DEADLOCK == return_value) {
				ldbm_nasty("ldbm_back_seq", "deadlock retry", 1601, err);
				/* just in case */
				slapi_ch_free(&(data.data));
				if ((key.data != little_buffer) && (key.data != &keystring)) {
					slapi_ch_free(&(key.data));
				}
				goto retry;
			}
		}
		if(retry_count == IDL_FETCH_RETRY_COUNT) {
			ldbm_nasty("ldbm_back_seq", "Retry count exceeded",1645,err);
		} else if ( err != 0 && err != DB_NOTFOUND ) {
			ldbm_nasty("ldbm_back_seq", "Database error", 1650, err);
		}
		slapi_ch_free( &(data.data) );
		if ( key.data != little_buffer && key.data != &keystring ) {
		    slapi_ch_free( &(key.data) );
		}
		slapi_ch_free_string( &big_buffer );
	}

	/* null idlist means there were no matching keys */
	if ( idl != NULL )
	{
		/*
		 * Step through the IDlist.  For each ID, get the entry
		 * and send it.
		 */
		ID id;
		struct backentry	*e;
		for ( id = idl_firstid( idl ); id != NOID;
			id = idl_nextid( idl, id ))
		{
		    if (( e = id2entry( be, id, &txn, &err )) == NULL )
		    {
				if ( err != LDAP_SUCCESS )
				{
				    slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_seq", "id2entry err %d\n", err);
				}
				slapi_log_err(SLAPI_LOG_ARGS,
					"ldbm_back_seq", "candidate %lu not found\n",
					(u_long)id);
				continue;
		    }
		    if ( slapi_send_ldap_search_entry( pb, e->ep_entry, NULL, NULL, 0 ) == 0 )
		    {
				nentries++;
		    }
		    CACHE_RETURN( &inst->inst_cache, &e );
		}
		idl_free( &idl );
	}
	/* if success finally commit the transaction, otherwise abort if DB_NOTFOUND */
	if(txn.back_txn_txn){
		if (return_value == 0) {
			dblayer_read_txn_commit(be, &txn);
		} else if (DB_NOTFOUND == return_value){
			dblayer_read_txn_abort(be, &txn);
		}
	}

	dblayer_release_index_file( be, ai, db );

	slapi_send_ldap_result( pb, LDAP_SUCCESS == err ? LDAP_SUCCESS : LDAP_OPERATIONS_ERROR, NULL, NULL, nentries, NULL );

	return 0;
}
示例#8
0
文件: ptpreop.c 项目: leto/389-ds
static int
passthru_bindpreop( Slapi_PBlock *pb )
{
    int			rc, method, freeresctrls=1;
    char		*matcheddn;
    const char	*normbinddn = NULL;
    Slapi_DN	*sdn = NULL;
    char		*libldap_errmsg, *pr_errmsg, *errmsg;
    PassThruConfig	*cfg;
    PassThruServer	*srvr;
    struct berval	*creds, **urls;
    LDAPControl		**reqctrls, **resctrls;

    PASSTHRU_ASSERT( pb != NULL );

    slapi_log_error( SLAPI_LOG_PLUGIN, PASSTHRU_PLUGIN_SUBSYSTEM,
	    "=> passthru_bindpreop\n" );

    /*
     * retrieve parameters for bind operation
     */
    if ( slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method ) != 0 ||
        slapi_pblock_get( pb, SLAPI_BIND_TARGET_SDN, &sdn ) != 0 ||
        slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &creds ) != 0 ) {
        slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
                     "<= not handled (unable to retrieve bind parameters)\n" );
        return( PASSTHRU_OP_NOT_HANDLED );
    }
    normbinddn = slapi_sdn_get_dn(sdn);
    if ( normbinddn == NULL ) {
        normbinddn = "";
    }

    /*
     * We only handle simple bind requests that include non-NULL binddn and
     * credentials.  Let the Directory Server itself handle everything else.
     */
    if ( method != LDAP_AUTH_SIMPLE || *normbinddn == '\0'
	    || creds->bv_len == 0 ) {
	slapi_log_error( SLAPI_LOG_PLUGIN, PASSTHRU_PLUGIN_SUBSYSTEM,
		"<= not handled (not simple bind or NULL dn/credentials)\n" );
	return( PASSTHRU_OP_NOT_HANDLED );
    }

    /*
     * Get pass through authentication configuration.
     */
    cfg = passthru_get_config();

    /*
     * Check to see if the target DN is one we should "pass through" to
     * another server.
     */
    if ( passthru_dn2server( cfg, normbinddn, &srvr ) != LDAP_SUCCESS ) {
	slapi_log_error( SLAPI_LOG_PLUGIN, PASSTHRU_PLUGIN_SUBSYSTEM,
		"<= not handled (not one of our suffixes)\n" );
	return( PASSTHRU_OP_NOT_HANDLED );
    }

    /*
     * We are now committed to handling this bind request.
     * Chain it off to another server.
     */
    matcheddn = errmsg = libldap_errmsg = pr_errmsg = NULL;
    urls = NULL;
    resctrls = NULL;
    if ( slapi_pblock_get( pb, SLAPI_REQCONTROLS, &reqctrls ) != 0 ) {
	rc = LDAP_OPERATIONS_ERROR;
	errmsg = "unable to retrieve bind controls";
	slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM, "%s\n",
		errmsg );
    } else {
	int	lderrno;

	if (( rc = passthru_simple_bind_s( pb, srvr, PASSTHRU_CONN_TRIES,
		normbinddn, creds, reqctrls, &lderrno, &matcheddn,
		&libldap_errmsg, &urls, &resctrls )) == LDAP_SUCCESS ) {
	    rc = lderrno;
	    errmsg = libldap_errmsg;
	} else if ( rc != LDAP_USER_CANCELLED ) {	/* not abandoned */
	    PRErrorCode	prerr = PR_GetError();
	    pr_errmsg = PR_smprintf( "error %d - %s %s ("
		    SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
		    rc, ldap_err2string( rc ), srvr->ptsrvr_url,
		    prerr, slapd_pr_strerror(prerr));
	    if ( NULL != pr_errmsg ) {
		errmsg = pr_errmsg;
	    } else {
		errmsg = ldap_err2string( rc );
	    }
	    rc = LDAP_OPERATIONS_ERROR;
	}
    }

    /*
     * If bind succeeded, change authentication information associated
     * with this connection.
     */
    if ( rc == LDAP_SUCCESS ) {
        char *ndn = slapi_ch_strdup( normbinddn );
        if (slapi_pblock_set(pb, SLAPI_CONN_DN, ndn) != 0 ||
	    slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD,
                             SLAPD_AUTH_SIMPLE) != 0) {
            slapi_ch_free((void **)&ndn);
            rc = LDAP_OPERATIONS_ERROR;
            errmsg = "unable to set connection DN or AUTHTYPE";
            slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
                             "%s\n", errmsg );
        }
    }

    if ( rc != LDAP_USER_CANCELLED ) {	/* not abandoned */
	/*
	 * Send a result to our client.
	 */
	if ( resctrls != NULL ) {
	    (void)slapi_pblock_set( pb, SLAPI_RESCONTROLS, resctrls );
            freeresctrls=0;
	}
	slapi_send_ldap_result( pb, rc, matcheddn, errmsg, 0, urls );
    }

    /*
     * Clean up -- free allocated memory, etc.
     */
    if ( urls != NULL ) {
	passthru_free_bervals( urls );
    }
    if ( libldap_errmsg != NULL ) {
	ldap_memfree( errmsg );
    }
    if ( pr_errmsg != NULL ) {
	PR_smprintf_free( pr_errmsg );
    }
    if ( freeresctrls && (resctrls != NULL) ) {
	ldap_controls_free( resctrls );
    }
    if ( matcheddn != NULL ) {
	ldap_memfree( matcheddn );
    }
 
    slapi_log_error( SLAPI_LOG_PLUGIN, PASSTHRU_PLUGIN_SUBSYSTEM,
	    "<= handled (error %d - %s)\n", rc, ldap_err2string( rc ));

    return( PASSTHRU_OP_HANDLED );
}
示例#9
0
文件: uid.c 项目: ohamada/389ds
/*
 * preop_modrdn - Pre-operation call for modify RDN
 *
 * Check that the new RDN does not include attributes that
 * cause a constraint violation
 */
static int
preop_modrdn(Slapi_PBlock *pb)
{
  int result = LDAP_SUCCESS;
  Slapi_Entry *e = NULL;
  Slapi_Value *sv_requiredObjectClass = NULL;
  char *errtext = NULL;
  char *attrName = NULL;

#ifdef DEBUG
    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
      "MODRDN begin\n");
#endif

  BEGIN
    int err;
    char *markerObjectClass=NULL;
    char *requiredObjectClass=NULL;
    Slapi_DN *sdn = NULL;
    Slapi_DN *superior;
    char *rdn;
    int deloldrdn = 0;
    int isupdatedn;
    Slapi_Attr *attr;
    int argc;
    char **argv = NULL;

        /*
         * If this is a replication update, just be a noop.
         */
        err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn);
    if (err) { result = uid_op_error(30); break; }
        if (isupdatedn)
        {
          break;
        }

    /*
     * Get the arguments
     */
        result = getArguments(pb, &attrName, &markerObjectClass,
                                                  &requiredObjectClass);
        if (UNTAGGED_PARAMETER == result)
        {
          result = LDAP_SUCCESS;
          /* Statically defined subtrees to monitor */
          err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc);
          if (err) { result = uid_op_error(53); break; }

          err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);
          if (err) { result = uid_op_error(54); break; }
          argc--; /* First argument was attribute name */
          argv++; 
        } else if (0 != result)
        {
          break;
        }

    /* Create a Slapi_Value for the requiredObjectClass to use
     * for checking the entry. */
    if (requiredObjectClass) {
        sv_requiredObjectClass = slapi_value_new_string(requiredObjectClass);
    }

    /* Get the DN of the entry being renamed */
    err = slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_SDN, &sdn);
    if (err) { result = uid_op_error(31); break; }

    /* Get superior value - unimplemented in 3.0/4.0/5.0 DS */
    err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &superior);
    if (err) { result = uid_op_error(32); break; }

    /*
     * No superior means the entry is just renamed at
     * its current level in the tree.  Use the target DN for
     * determining which managed tree this belongs to
     */
    if (!superior) superior = sdn;

    /* Get the new RDN - this has the attribute values */
    err = slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &rdn);
    if (err) { result = uid_op_error(33); break; }
#ifdef DEBUG
    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
      "MODRDN newrdn=%s\n", rdn);
#endif

    /* See if the old RDN value is being deleted. */
    err = slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn);
    if (err) { result = uid_op_error(34); break; }

    /* Get the entry that is being renamed so we can make a dummy copy
     * of what it will look like after the rename. */
    err = slapi_search_internal_get_entry(sdn, NULL, &e, plugin_identity);
    if (err != LDAP_SUCCESS) {
        result = uid_op_error(35);
        /* We want to return a no such object error if the target doesn't exist. */
        if (err == LDAP_NO_SUCH_OBJECT) {
            result = err;
        }
        break;
    }

    /* Apply the rename operation to the dummy entry. */
    /* slapi_entry_rename does not expect rdn normalized */
    err = slapi_entry_rename(e, rdn, deloldrdn, superior);
    if (err != LDAP_SUCCESS) { result = uid_op_error(36); break; }

        /*
         * Find any unique attribute data in the new RDN
         */
        err = slapi_entry_attr_find(e, attrName, &attr);
        if (err) break;  /* no UID attribute */

        /*
         * Check if it has the required object class
         */
        if (requiredObjectClass &&
            !slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sv_requiredObjectClass)) { break; }

        /*
         * Passed all the requirements - this is an operation we
         * need to enforce uniqueness on. Now find all parent entries
         * with the marker object class, and do a search for each one.
         */
        if (NULL != markerObjectClass)
        {
          /* Subtree defined by location of marker object class */
                result = findSubtreeAndSearch(slapi_entry_get_sdn(e), attrName, attr, NULL,
                                              requiredObjectClass, sdn,
                                              markerObjectClass);
        } else
        {
          /* Subtrees listed on invocation line */
          result = searchAllSubtrees(argc, argv, attrName, attr, NULL,
                                     requiredObjectClass, sdn);
        }
  END
  /* Clean-up */
  slapi_value_free(&sv_requiredObjectClass);
  if (e) slapi_entry_free(e);

  if (result)
  {
    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
      "MODRDN result %d\n", result);

    if (result == LDAP_CONSTRAINT_VIOLATION) {
      errtext = slapi_ch_smprintf(moreInfo, attrName);
    } else {
      errtext = slapi_ch_strdup("Error checking for attribute uniqueness.");
    }

    slapi_send_ldap_result(pb, result, 0, errtext, 0, 0);

    slapi_ch_free_string(&errtext);
  }

  return (result==LDAP_SUCCESS)?0:-1;

}
示例#10
0
文件: uid.c 项目: ohamada/389ds
/*
 * preop_modify - pre-operation plug-in for modify
 */
static int
preop_modify(Slapi_PBlock *pb)
{

  int result = LDAP_SUCCESS;
  Slapi_PBlock *spb = NULL;
  LDAPMod **checkmods = NULL;
  int checkmodsCapacity = 0;
  char *errtext = NULL;
  char *attrName = NULL;

#ifdef DEBUG
    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
      "MODIFY begin\n");
#endif

  BEGIN
    int err;
    char *markerObjectClass=NULL;
    char *requiredObjectClass=NULL;
    LDAPMod **mods;
    int modcount = 0;
    int ii;
    LDAPMod *mod;
    Slapi_DN *sdn = NULL;
    int isupdatedn;
    int argc;
    char **argv = NULL;

    /*
     * If this is a replication update, just be a noop.
     */
    err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn);
    if (err) { result = uid_op_error(60); break; }
    if (isupdatedn)
    {
      break;
    }

    /*
     * Get the arguments
     */
        result = getArguments(pb, &attrName, &markerObjectClass,
                                                  &requiredObjectClass);
        if (UNTAGGED_PARAMETER == result)
        {
          result = LDAP_SUCCESS;
          /* Statically defined subtrees to monitor */
          err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc);
          if (err) { result = uid_op_error(53); break; }

          err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);
          if (err) { result = uid_op_error(54); break; }
          argc--; /* First argument was attribute name */
          argv++;
        } else if (0 != result)
        {
          break;
        }

    err = slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
    if (err) { result = uid_op_error(61); break; }

    /* There may be more than one mod that matches e.g.
       changetype: modify
       delete: uid
       uid: balster1950
       -
       add: uid
       uid: scottg
       
       So, we need to first find all mods that contain the attribute
       which are add or replace ops and are bvalue encoded
    */
    /* find out how many mods meet this criteria */
    for(;*mods;mods++)
    {
        mod = *mods;
        if ((slapi_attr_type_cmp(mod->mod_type, attrName, 1) == 0) && /* mod contains target attr */
            (mod->mod_op & LDAP_MOD_BVALUES) && /* mod is bval encoded (not string val) */
            (mod->mod_bvalues && mod->mod_bvalues[0]) && /* mod actually contains some values */
            (SLAPI_IS_MOD_ADD(mod->mod_op) || /* mod is add */
             SLAPI_IS_MOD_REPLACE(mod->mod_op))) /* mod is replace */
        {
          addMod(&checkmods, &checkmodsCapacity, &modcount, mod);
        }
    }
    if (modcount == 0) {
        break; /* no mods to check, we are done */
    }

    /* Get the target DN */
    err = slapi_pblock_get(pb, SLAPI_MODIFY_TARGET_SDN, &sdn);
    if (err) { result = uid_op_error(11); break; }

    /*
     * Check if it has the required object class
     */
    if (requiredObjectClass &&
        !(spb = dnHasObjectClass(sdn, requiredObjectClass))) {
        break;
    }

    /*
     * Passed all the requirements - this is an operation we
     * need to enforce uniqueness on. Now find all parent entries
     * with the marker object class, and do a search for each one.
     */
    /*
     * stop checking at first mod that fails the check
     */
    for (ii = 0; (result == 0) && (ii < modcount); ++ii)
    {
        mod = checkmods[ii];
        if (NULL != markerObjectClass)
        {
            /* Subtree defined by location of marker object class */
            result = findSubtreeAndSearch(sdn, attrName, NULL, 
                                          mod->mod_bvalues, requiredObjectClass,
                                          sdn, markerObjectClass);
        } else
        {
            /* Subtrees listed on invocation line */
            result = searchAllSubtrees(argc, argv, attrName, NULL,
                                       mod->mod_bvalues, requiredObjectClass, sdn);
        }
    }
  END

  slapi_ch_free((void **)&checkmods);
  freePblock(spb);
 if (result)
  {
    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
      "MODIFY result %d\n", result);

    if (result == LDAP_CONSTRAINT_VIOLATION) {
      errtext = slapi_ch_smprintf(moreInfo, attrName);
    } else {
      errtext = slapi_ch_strdup("Error checking for attribute uniqueness.");
    }

    slapi_send_ldap_result(pb, result, 0, errtext, 0, 0);

    slapi_ch_free_string(&errtext);
  }

  return (result==LDAP_SUCCESS)?0:-1;

}
示例#11
0
文件: uid.c 项目: ohamada/389ds
/*
 * preop_add - pre-operation plug-in for add
 */
static int
preop_add(Slapi_PBlock *pb)
{
  int result;
  char *errtext = NULL;
  char *attrName = NULL;

#ifdef DEBUG
  slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD begin\n");
#endif

  result = LDAP_SUCCESS;

  /*
   * Do constraint check on the added entry.  Set result.
   */

 BEGIN
    int err;
    char *markerObjectClass = NULL;
    char *requiredObjectClass = NULL;
    Slapi_DN *sdn = NULL;
    int isupdatedn;
    Slapi_Entry *e;
    Slapi_Attr *attr;
    int argc;
    char **argv = NULL;

        /*
         * If this is a replication update, just be a noop.
         */
        err = slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isupdatedn);
    if (err) { result = uid_op_error(50); break; }
        if (isupdatedn)
        {
          break;
        }

    /*
     * Get the arguments
     */
        result = getArguments(pb, &attrName, &markerObjectClass,
                                                  &requiredObjectClass);
        if (UNTAGGED_PARAMETER == result)
        {
          slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, 
                          "ADD parameter untagged: %s\n", attrName);
          result = LDAP_SUCCESS;
          /* Statically defined subtrees to monitor */
          err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc);
          if (err) { result = uid_op_error(53); break; }

          err = slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);
          if (err) { result = uid_op_error(54); break; }
          argc--; argv++; /* First argument was attribute name */
        } else if (0 != result)
        {
          break;
        }

    /*
     * Get the target DN for this add operation
     */
    err = slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
    if (err) { result = uid_op_error(51); break; }

#ifdef DEBUG
    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "ADD target=%s\n", slapi_sdn_get_dn(sdn));
#endif

       /*
         * Get the entry data for this add. Check whether it
         * contains a value for the unique attribute
         */
        err = slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
        if (err) { result = uid_op_error(52); break; }

        err = slapi_entry_attr_find(e, attrName, &attr);
        if (err) break;  /* no unique attribute */

        /*
         * Check if it contains the required object class
         */
        if (NULL != requiredObjectClass)
        {
          if (!entryHasObjectClass(pb, e, requiredObjectClass))
          {
                /* No, so we don't have to do anything */
                break;
          }
        }

        /*
         * Passed all the requirements - this is an operation we
         * need to enforce uniqueness on. Now find all parent entries
         * with the marker object class, and do a search for each one.
         */
        if (NULL != markerObjectClass)
        {
          /* Subtree defined by location of marker object class */
                result = findSubtreeAndSearch(sdn, attrName, attr, NULL,
                                              requiredObjectClass, sdn,
                                              markerObjectClass);
        } else
        {
          /* Subtrees listed on invocation line */
          result = searchAllSubtrees(argc, argv, attrName, attr, NULL,
                                     requiredObjectClass, sdn);
        }
  END

  if (result)
  {
    slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name,
      "ADD result %d\n", result);

    if (result == LDAP_CONSTRAINT_VIOLATION) {
      errtext = slapi_ch_smprintf(moreInfo, attrName);
    } else {
      errtext = slapi_ch_strdup("Error checking for attribute uniqueness.");
    }

    /* Send failure to the client */
    slapi_send_ldap_result(pb, result, 0, errtext, 0, 0);

    slapi_ch_free_string(&errtext);
  }

  return (result==LDAP_SUCCESS)?0:-1;
}
示例#12
0
static int
nullsuffix_search( Slapi_PBlock *pb )
{
	char			*dn_base, **attrs, *newStr;
	int				scope, sizelimit, timelimit, deref, attrsonly;
	Slapi_Filter	*filter;
	Slapi_DN		*sdn_base;
	int				ldaperr = LDAP_SUCCESS;	/* optimistic */
	int				nentries = 0;	/* entry count */
	int				i;
	Slapi_Operation	*op;
	Slapi_Entry		*e;

	const char *entrystr =
		"dn:cn=Joe Smith,o=Example\n"
		"objectClass: top\n"
		"objectClass: person\n"
		"objectClass: organizationalPerson\n"
		"objectClass: inetOrgPerson\n"
		"cn:Joe Smith\n"
		"sn:Smith\n"
		"uid:jsmith\n"
		"mail:[email protected]\n";
	
	slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME, "nullsuffix_search\n" );
	if( slapi_op_reserved(pb) ){
		return PLUGIN_OPERATION_IGNORED;
	}

	/* get essential search parameters */
	if ( slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &dn_base ) != 0 ||
			slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ) != 0 ) {
		slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
				"could not get base DN and scope search parameters\n" );
	}
	if ( dn_base == NULL ) {
		dn_base = "";
	}
	sdn_base = slapi_sdn_new_dn_byval( dn_base );
	slapi_pblock_get(pb, SLAPI_OPERATION, &op);

	/* get remaining search parameters */
	if ( slapi_pblock_get( pb, SLAPI_SEARCH_DEREF, &deref ) != 0 ||
			slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit ) != 0 ||
			slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit ) != 0 ||
			slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ) != 0 ||
			slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs ) != 0 ||
			slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly ) != 0 ) {
		slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
				"could not get remaining search parameters\n" );
	}

	if ( slapi_pblock_get( pb, SLAPI_OPERATION, &op ) != 0 ) {
		slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
				"could not get operation\n" );
	} else {
		 slapi_operation_set_flag(op, SLAPI_OP_FLAG_NO_ACCESS_CHECK  );
	}

	/* create a fake entry and send it along */
	newStr = slapi_ch_strdup( entrystr );
	if ( NULL == ( e = slapi_str2entry( newStr,
				SLAPI_STR2ENTRY_ADDRDNVALS
				| SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES ))) {
		slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME,
				"nullsuffix_search: slapi_str2entry() failed\n" );
	} else {
		slapi_send_ldap_search_entry( pb, e, NULL /* controls */,
				attrs, attrsonly );
		++nentries;
		slapi_entry_free( e );
	}

	slapi_send_ldap_result( pb, ldaperr, NULL, "kilroy was here",
			nentries, NULL );
	slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME, "nullsuffix_search:"
			" handled search based at %s with scope %d; ldaperr=%d\n",
			dn_base, scope, ldaperr );

	slapi_ch_free_string(&newStr);
	slapi_sdn_free(&sdn_base);

	return PLUGIN_OPERATION_HANDLED;
}
示例#13
0
int
ldbm_back_modify( Slapi_PBlock *pb )
{
	backend *be;
	ldbm_instance *inst = NULL;
	struct ldbminfo		*li;
	struct backentry	*e = NULL, *ec = NULL;
	struct backentry	*original_entry = NULL, *tmpentry = NULL;
	Slapi_Entry		*postentry = NULL;
	LDAPMod			**mods = NULL;
	LDAPMod			**mods_original = NULL;
	Slapi_Mods smods = {0};
	back_txn txn;
	back_txnid		parent_txn;
	modify_context		ruv_c = {0};
	int			ruv_c_init = 0;
	int			retval = -1;
	char			*msg;
	char			*errbuf = NULL;
	int retry_count = 0;
	int disk_full = 0;
	int ldap_result_code= LDAP_SUCCESS;
	char *ldap_result_message= NULL;
	int rc = 0;
	Slapi_Operation *operation;
	entry_address *addr;
	int is_fixup_operation= 0;
	int is_ruv = 0;                 /* True if the current entry is RUV */
	CSN *opcsn = NULL;
	int repl_op;
	int opreturn = 0;
	int mod_count = 0;
	int not_an_error = 0;
	int fixup_tombstone = 0;
	int ec_locked = 0;
	int result_sent = 0;

	slapi_pblock_get( pb, SLAPI_BACKEND, &be);
	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
	slapi_pblock_get( pb, SLAPI_TARGET_ADDRESS, &addr );
	slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
	slapi_pblock_get( pb, SLAPI_TXN, (void**)&parent_txn );
	slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);
	slapi_pblock_get( pb, SLAPI_OPERATION, &operation );

	fixup_tombstone = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_FIXUP);

	dblayer_txn_init(li,&txn); /* must do this before first goto error_return */
	/* the calls to perform searches require the parent txn if any
	   so set txn to the parent_txn until we begin the child transaction */
	if (parent_txn) {
		txn.back_txn_txn = parent_txn;
	} else {
		parent_txn = txn.back_txn_txn;
		slapi_pblock_set( pb, SLAPI_TXN, parent_txn );
	}

	if (NULL == operation)
	{
		ldap_result_code = LDAP_OPERATIONS_ERROR;
		goto error_return;
	}

	is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
	is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
	inst = (ldbm_instance *) be->be_instance_info;

	if (NULL == addr)
	{
		goto error_return;
	}
	if (inst && inst->inst_ref_count) {
		slapi_counter_increment(inst->inst_ref_count);
	} else {
		slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
		              "Instance \"%s\" does not exist.\n",
		              inst ? inst->inst_name : "null instance");
		goto error_return;
	}

	/* no need to check the dn syntax as this is a replicated op */
	if(!repl_op){
		ldap_result_code = slapi_dn_syntax_check(pb, slapi_sdn_get_dn(addr->sdn), 1);
		if (ldap_result_code)
		{
			ldap_result_code = LDAP_INVALID_DN_SYNTAX;
			slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
			goto error_return;
		}
	}

	/* The dblock serializes writes to the database,
	 * which reduces deadlocking in the db code,
	 * which means that we run faster.
	 *
	 * But, this lock is re-enterant for the fixup
	 * operations that the URP code in the Replication
	 * plugin generates.
	 *
	 * SERIALLOCK is moved to dblayer_txn_begin along with exposing be
	 * transaction to plugins (see slapi_back_transaction_* APIs).
	 *
	if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP)) {
		dblayer_lock_backend(be);
		dblock_acquired= 1;
	}
	 */
	if ( MANAGE_ENTRY_BEFORE_DBLOCK(li)) {
		/* find and lock the entry we are about to modify */
		if (fixup_tombstone) {
			e = find_entry2modify_only_ext( pb, be, addr, TOMBSTONE_INCLUDED, &txn, &result_sent );
		} else {
			e = find_entry2modify( pb, be, addr, &txn, &result_sent );
		}
		if (e == NULL) {
			ldap_result_code = -1;
			goto error_return; /* error result sent by find_entry2modify() */
		}
	}

	txn.back_txn_txn = NULL; /* ready to create the child transaction */
	for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
		int cache_rc = 0;
		int new_mod_count = 0;
		if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
			/* don't release SERIAL LOCK */
			dblayer_txn_abort_ext(li, &txn, PR_FALSE); 
			slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
			/*
			 * Since be_txn_preop functions could have modified the entry/mods,
			 * We need to grab the current mods, free them, and restore the
			 * originals.  Same thing for the entry.
			 */
			
			slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
			ldap_mods_free(mods, 1);
			slapi_pblock_set(pb, SLAPI_MODIFY_MODS, copy_mods(mods_original));

			/* reset ec set cache in id2entry_add_ext */
			if (ec) {
				/* must duplicate ec before returning it to cache,
				 * which could free the entry. */
				if ((tmpentry = backentry_dup(original_entry?original_entry:ec)) == NULL) {
					ldap_result_code= LDAP_OPERATIONS_ERROR;
					goto error_return;
				}
				if (cache_is_in_cache(&inst->inst_cache, ec)) {
					CACHE_REMOVE(&inst->inst_cache, ec);
				}
				CACHE_RETURN(&inst->inst_cache, &ec);
				slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, original_entry->ep_entry );
				ec = original_entry;
				original_entry = tmpentry;
				tmpentry = NULL;
			}

			if (ruv_c_init) {
				/* reset the ruv txn stuff */
				modify_term(&ruv_c, be);
				ruv_c_init = 0;
			}

			slapi_log_err(SLAPI_LOG_BACKLDBM, "ldbm_back_modify",
			               "Modify Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
			{
			PRIntervalTime interval;
			interval = PR_MillisecondsToInterval(slapi_rand() % 100);
			DS_Sleep(interval);
			}
#endif
		}

		/* Nothing above here modifies persistent store, everything after here is subject to the transaction */
		/* dblayer_txn_begin holds SERIAL lock, 
		 * which should be outside of locking the entry (find_entry2modify) */
		if (0 == retry_count) {
			/* First time, hold SERIAL LOCK */
			retval = dblayer_txn_begin(be, parent_txn, &txn);
		} else {
			/* Otherwise, no SERIAL LOCK */
			retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE);
		}
		if (0 != retval) {
			if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
			ldap_result_code= LDAP_OPERATIONS_ERROR;
			goto error_return;
		}
		/* stash the transaction for plugins */
		slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);

		if (0 == retry_count) { /* just once */
			if ( !MANAGE_ENTRY_BEFORE_DBLOCK(li)) {
				/* find and lock the entry we are about to modify */
				if (fixup_tombstone) {
					e = find_entry2modify_only_ext( pb, be, addr, TOMBSTONE_INCLUDED, &txn, &result_sent );
				} else {
					e = find_entry2modify( pb, be, addr, &txn, &result_sent );
				}
				if (e == NULL) {
					ldap_result_code = -1;
					goto error_return; /* error result sent by find_entry2modify() */
				}
			}
		
			if ( !is_fixup_operation && !fixup_tombstone)
			{
				if (!repl_op && slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE))
				{
					ldap_result_code = LDAP_UNWILLING_TO_PERFORM;
                			ldap_result_message = "Operation not allowed on tombstone entry.";
					slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
						"Attempt to modify a tombstone entry %s\n",
						slapi_sdn_get_dn(slapi_entry_get_sdn_const( e->ep_entry )));
					goto error_return;
				}
				opcsn = operation_get_csn (operation);
				if (NULL == opcsn && operation->o_csngen_handler)
				{
					/*
					 * Current op is a user request. Opcsn will be assigned
					 * if the dn is in an updatable replica.
					 */
					opcsn = entry_assign_operation_csn ( pb, e->ep_entry, NULL );
				}
				if (opcsn)
				{
					entry_set_maxcsn (e->ep_entry, opcsn);
				}
			}
		
			/* Save away a copy of the entry, before modifications */
			slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
			
			if ( (ldap_result_code = plugin_call_acl_mods_access( pb, e->ep_entry, mods, &errbuf)) != LDAP_SUCCESS ) {
				ldap_result_message= errbuf;
				goto error_return;
			}
		
			/* create a copy of the entry and apply the changes to it */
			if ( (ec = backentry_dup( e )) == NULL ) {
				ldap_result_code= LDAP_OPERATIONS_ERROR;
				goto error_return;
			}
		
			if(!repl_op){
			    remove_illegal_mods(mods);
			}
		
			/* ec is the entry that our bepreop should get to mess with */
			slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, ec->ep_entry );
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
		
			opreturn = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN);
			if (opreturn ||
				(slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code) && ldap_result_code) ||
				(slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn) && opreturn)) {
				slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
				slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
				if (!ldap_result_code) {
					slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
						"SLAPI_PLUGIN_BE_PRE_MODIFY_FN "
						"returned error but did not set SLAPI_RESULT_CODE\n");
					ldap_result_code = LDAP_OPERATIONS_ERROR;
				}
				if (SLAPI_PLUGIN_NOOP == opreturn) {
					not_an_error = 1;
					rc = opreturn = LDAP_SUCCESS;
				} else if (!opreturn) {
					opreturn = SLAPI_PLUGIN_FAILURE;
					slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
				}
				slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
				goto error_return;
			}
			/* The Plugin may have messed about with some of the PBlock parameters... ie. mods */
			slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
		
			/* apply the mods, check for syntax, schema problems, etc. */
			if (modify_apply_check_expand(pb, operation, mods, e, ec, &postentry,
										  &ldap_result_code, &ldap_result_message)) {
				goto error_return;
			}
			/* the schema check could have added a repl conflict mod
			 * get the mods again */
			slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
			slapi_mods_init_byref(&smods,mods);
			mod_count = slapi_mods_get_num_mods(&smods);
			/*
			 * Grab a copy of the mods and the entry in case the be_txn_preop changes
			 * the them.  If we have a failure, then we need to reset the mods to their
			 * their original state;
			 */
			mods_original = copy_mods(mods);
			if ( (original_entry = backentry_dup( ec )) == NULL ) {
				ldap_result_code= LDAP_OPERATIONS_ERROR;
				goto error_return;
			}
		} /* if (0 == retry_count) just once */

		/* call the transaction pre modify plugins just after creating the transaction */
		retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN);
		if (retval) {
			slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_modify", "SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN plugin "
						   "returned error code %d\n", retval );
			slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
			slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
			if (SLAPI_PLUGIN_NOOP == retval) {
				not_an_error = 1;
				rc = retval = LDAP_SUCCESS;
			}
			if (!opreturn) {
				slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval);
			}
			slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
			goto error_return;
		}

		/* the mods might have been changed, so get the latest */
		slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );

		/* make sure the betxnpreop did not alter any of the mods that
		   had already previously been applied */
		slapi_mods_done(&smods);
		slapi_mods_init_byref(&smods,mods);
		new_mod_count = slapi_mods_get_num_mods(&smods);
		if (new_mod_count < mod_count) {
			slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
				"Error: BE_TXN_PRE_MODIFY plugin has removed "
				"mods from the original list - mod count was [%d] now [%d] "
				"mods will not be applied - mods list changes must be done "
				"in the BE_PRE_MODIFY plugin, not the BE_TXN_PRE_MODIFY\n",
				mod_count, new_mod_count );
		} else if (new_mod_count > mod_count) { /* apply the new betxnpremod mods */
			/* apply the mods, check for syntax, schema problems, etc. */
			if (modify_apply_check_expand(pb, operation, &mods[mod_count], e, ec, &postentry,
										  &ldap_result_code, &ldap_result_message)) {
				goto error_return;
			}
		} /* else if new_mod_count == mod_count then betxnpremod plugin did nothing */
			
		/*
		 * Update the ID to Entry index. 
		 * Note that id2entry_add replaces the entry, so the Entry ID 
		 * stays the same.
		 */
		retval = id2entry_add_ext( be, ec, &txn, 1, &cache_rc ); 
		if (DB_LOCK_DEADLOCK == retval)
		{
			/* Abort and re-try */
			continue;
		}
		if (0 != retval) {
			slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
				"id2entry_add failed, err=%d %s\n",
				retval, (msg = dblayer_strerror( retval )) ? msg : "");
			if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
			MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
			goto error_return;
		}
		retval = index_add_mods( be, mods, e, ec, &txn );
		if (DB_LOCK_DEADLOCK == retval)
		{
			/* Abort and re-try */
			continue;
		}
		if (0 != retval) {
			slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
				"index_add_mods failed, err=%d %s\n",
				retval, (msg = dblayer_strerror( retval )) ? msg : "");
			if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
			MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
			goto error_return;
		}
		/*
		 * Remove the old entry from the Virtual List View indexes.
		 * Add the new entry to the Virtual List View indexes.
		 * If the entry is ruv, no need to update vlv.
		 */
		if (!is_ruv) {
			retval= vlv_update_all_indexes(&txn, be, pb, e, ec);
			if (DB_LOCK_DEADLOCK == retval)
			{
				/* Abort and re-try */
				continue;
			}
			if (0 != retval) {
				slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
					"vlv_update_index failed, err=%d %s\n",
					retval, (msg = dblayer_strerror( retval )) ? msg : "");
				if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
				MOD_SET_ERROR(ldap_result_code, 
							  LDAP_OPERATIONS_ERROR, retry_count);
				goto error_return;
			}

		}

		if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
			ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
			if (-1 == ruv_c_init) {
				slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
					"ldbm_txn_ruv_modify_context failed to construct RUV modify context\n");
				ldap_result_code= LDAP_OPERATIONS_ERROR;
				retval = 0;
				goto error_return;
			}
		}

		if (ruv_c_init) {
			retval = modify_update_all( be, pb, &ruv_c, &txn );
			if (DB_LOCK_DEADLOCK == retval) {
				/* Abort and re-try */
				continue;
			}
			if (0 != retval) {
				slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
					"modify_update_all failed, err=%d %s\n", retval,
					(msg = dblayer_strerror( retval )) ? msg : "");
				if (LDBM_OS_ERR_IS_DISKFULL(retval))
					disk_full = 1;
				ldap_result_code= LDAP_OPERATIONS_ERROR;
				goto error_return;
			}
		}

		if (0 == retval) {
			break;
		}
	}
	if (retry_count == RETRY_TIMES) {
		slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
			"Retry count exceeded in modify\n");
	   	ldap_result_code= LDAP_BUSY;
		goto error_return;
	}

	if (ruv_c_init) {
		if (modify_switch_entries(&ruv_c, be) != 0 ) {
			ldap_result_code= LDAP_OPERATIONS_ERROR;
			slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modify",
				"modify_switch_entries failed\n");
			goto error_return;
		}
	}
	
	if (cache_replace( &inst->inst_cache, e, ec ) != 0 ) {
		MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
		goto error_return;
	}
	/* e uncached */
	/* we must return both e (which has been deleted) and new entry ec to cache */
	/* cache_replace removes e from the cache hash tables */
	cache_unlock_entry( &inst->inst_cache, e );
	CACHE_RETURN( &inst->inst_cache, &e );
	/* lock new entry in cache to prevent usage until we are complete */
	cache_lock_entry( &inst->inst_cache, ec );
	ec_locked = 1;
	postentry = slapi_entry_dup( ec->ep_entry );
	slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );

	/* invalidate virtual cache */
	ec->ep_entry->e_virtual_watermark = 0;

	/* 
	 * LP Fix of crash when the commit will fail:
	 * If the commit fail, the common error path will
	 * try to unlock the entry again and crash (PR_ASSERT
	 * in debug mode.
	 * By just setting e to NULL, we avoid this. It's OK since
	 * we don't use e after that in the normal case.
	 */
	e = NULL;
	
	/* call the transaction post modify plugins just before the commit */
	if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN))) {
		slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_modify",
			"SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN plugin "
			"returned error code %d\n", retval );
		if (!ldap_result_code) {
			slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
		}
		if (!opreturn) {
			slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
		}
		if (!opreturn) {
			slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval);
		}
		slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
		goto error_return;
	}

	/* Release SERIAL LOCK */
	retval = dblayer_txn_commit(be, &txn);
	/* after commit - txn is no longer valid - replace SLAPI_TXN with parent */
	slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
	if (0 != retval) {
		if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
		ldap_result_code= LDAP_OPERATIONS_ERROR;
		goto error_return;
	}

	rc= 0;
	goto common_return;

error_return:
	if ( postentry != NULL ) 
	{
		slapi_entry_free( postentry );
		postentry = NULL;
		slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, NULL );
	}
	if (retval == DB_RUNRECOVERY) {
	  dblayer_remember_disk_filled(li);
	  ldbm_nasty("ldbm_back_modify","Modify",81,retval);
	  disk_full = 1;
	}

	if (disk_full) {
	    rc= return_on_disk_full(li);
	} else {
		if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
			/* make sure SLAPI_RESULT_CODE and SLAPI_PLUGIN_OPRETURN are set */
			int val = 0;
			slapi_pblock_get(pb, SLAPI_RESULT_CODE, &val);
			if (!val) {
				if (!ldap_result_code) {
					ldap_result_code = LDAP_OPERATIONS_ERROR;
				}
				slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
			}
			slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &val );
			if (!val) {
				opreturn = -1;
				slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
			}
			/* call the transaction post modify plugins just before the abort */
			/* plugins called before abort should check for the OPRETURN or RESULT_CODE
			   and skip processing if they don't want do anything - some plugins that
			   keep track of a counter (usn, dna) may want to "rollback" the counter
			   in this case */
			if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN))) {
				slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_modify",
					"SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN plugin returned error code %d\n", retval );
				slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
				slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
				slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
				if (!opreturn) {
					slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval);
				}
			}

			/* It is safer not to abort when the transaction is not started. */
			/* Release SERIAL LOCK */
			dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */
			/* txn is no longer valid - reset the txn pointer to the parent */
			slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
		}
		if (!not_an_error) {
			rc = SLAPI_FAIL_GENERAL;
		}
	}

	/* if ec is in cache, remove it, then add back e if we still have it */
	if (inst && cache_is_in_cache(&inst->inst_cache, ec)) {
		CACHE_REMOVE( &inst->inst_cache, ec );
		/* if ec was in cache, e was not - add back e */
		if (e) {
			if (CACHE_ADD( &inst->inst_cache, e, NULL ) < 0) {
				slapi_log_err(SLAPI_LOG_CACHE, "ldbm_back_modify", "CACHE_ADD %s failed\n",
				              slapi_entry_get_dn(e->ep_entry));
			}
		}
	}

common_return:
	slapi_mods_done(&smods);
	
	if (inst) {
		if (ec_locked || cache_is_in_cache(&inst->inst_cache, ec)) {
			cache_unlock_entry(&inst->inst_cache, ec);
		} else if (e) {
			/* if ec was not in cache, cache_replace was not done.
			 * i.e., e was not unlocked. */
			cache_unlock_entry(&inst->inst_cache, e);
			CACHE_RETURN(&inst->inst_cache, &e);
		}
		CACHE_RETURN(&inst->inst_cache, &ec);
		if (inst->inst_ref_count) {
			slapi_counter_decrement(inst->inst_ref_count);
		}
	}

	/* result code could be used in the bepost plugin functions. */
	slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);

	/* The bepostop is called even if the operation fails. */
	if (!disk_full)
		plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN);

	if (ruv_c_init) {
		modify_term(&ruv_c, be);
	}

	if (ldap_result_code == -1) {
		/* Reset to LDAP_NO_SUCH_OBJECT*/
		ldap_result_code = LDAP_NO_SUCH_OBJECT;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
	} else {
		if (not_an_error) {
			/* This is mainly used by urp.  Solved conflict is not an error.
			 * And we don't want the supplier to halt sending the updates. */
			ldap_result_code = LDAP_SUCCESS;
		}
		if (!result_sent) {
			/* result is already sent in find_entry. */
			slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
		}
	}

	/* free our backups */
	ldap_mods_free(mods_original, 1);
	backentry_free(&original_entry);
	backentry_free(&tmpentry);
	slapi_ch_free_string(&errbuf);

	return rc;
}
示例#14
0
文件: aclplugin.c 项目: Firstyear/ds
/*
 * Common function that is called by aclplugin_preop_search() and
 * aclplugin_preop_modify().
 *
 * Return values:
 *	0 - all is well; proceed.
 *  1 - fatal error; result has been sent to client.
 */ 
int
aclplugin_preop_common( Slapi_PBlock *pb )
{
	char		*proxy_dn = NULL;	/* id being assumed */
	char		*dn;		/* proxy master */
	char		*errtext = NULL;
	int			lderr;
	Acl_PBlock	*aclpb;

	TNF_PROBE_0_DEBUG(aclplugin_preop_common_start ,"ACL","");

	aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );

	if (aclpb == NULL) {
		slapi_log_err(SLAPI_LOG_ACL, plugin_name, "aclplugin_preop_common - Error: aclpb is NULL\n" );
		slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
		return 1;
	}

        /* See if we have initialized already */
        if ( aclpb->aclpb_state & ACLPB_INITIALIZED ) goto done;

	/*
	 * The following mallocs memory for proxy_dn, but not the dn.
	 * The proxy_dn is the id being assumed, while dn
	 * is the "proxy master".
	*/
	if ( LDAP_SUCCESS != ( lderr = proxyauth_get_dn( pb, &proxy_dn, &errtext ))) {
		/*
		 * Fatal error -- send a result to the client and arrange to skip
		 * any further processing.
		 */
		slapi_send_ldap_result( pb, lderr, NULL, errtext, 0, NULL );
		TNF_PROBE_1_DEBUG(aclplugin_preop_common_end ,"ACL","",
						tnf_string,proxid_error,"");
		slapi_ch_free_string(&proxy_dn);
		return 1;	/* skip any further processing */
	}
	slapi_pblock_get ( pb, SLAPI_REQUESTOR_DN, &dn );


	/*
	 * The dn is copied into the aclpb during initialization.
	*/
	if ( proxy_dn) {
		TNF_PROBE_0_DEBUG(proxyacpb_init_start,"ACL","");

		slapi_log_err(SLAPI_LOG_ACL, plugin_name,
				"aclplugin_preop_common - Proxied authorization dn is (%s)\n", proxy_dn );
		acl_init_aclpb ( pb, aclpb, proxy_dn, 1 );
		aclpb = acl_new_proxy_aclpb ( pb );
		acl_init_aclpb ( pb, aclpb, dn, 0 );
		slapi_ch_free ( (void **) &proxy_dn );
		
		TNF_PROBE_0_DEBUG(proxyacpb_init_end,"ACL","");
 
	} else {
		TNF_PROBE_0_DEBUG(aclpb_init_start,"ACL","");
		acl_init_aclpb ( pb, aclpb, dn, 1 );
		TNF_PROBE_0_DEBUG(aclpb_init_end,"ACL","");

	}

done:
	TNF_PROBE_0_DEBUG(aclplugin_preop_common_end ,"ACL","");

	return 0;
}
示例#15
0
文件: pam_ptimpl.c 项目: leto/389-ds
/*
 * Do the actual work of authenticating with PAM. First, get the PAM identity
 * based on the method used to convert the BIND identity to the PAM identity.
 * Set up the structures that pam_start needs and call pam_start().  After
 * that, call pam_authenticate and pam_acct_mgmt.  Check the various return
 * values from these functions and map them to their corresponding LDAP BIND
 * return values.  Return the appropriate LDAP error code.
 * This function will also set the appropriate LDAP response controls in
 * the given pblock.
 * Since this function can be called multiple times, we only want to return
 * the errors and controls to the user if this is the final call, so the
 * final_method parameter tells us if this is the last one.  Coupled with
 * the fallback argument, we can tell if we are able to send the response
 * back to the client.
 */
static int
do_one_pam_auth(
	Slapi_PBlock *pb,
	int method, /* get pam identity from ENTRY, RDN, or DN */
	PRBool final_method, /* which method is the last one to try */
	char *pam_service, /* name of service for pam_start() */
	char *map_ident_attr, /* for ENTRY method, name of attribute holding pam identity */
	PRBool fallback, /* if true, failure here should fallback to regular bind */
	int pw_response_requested /* do we need to send pwd policy resp control */
)
{
	MyStrBuf pam_id;
	const char *binddn = NULL;
	Slapi_DN *bindsdn = NULL;
	int rc;
	int retcode = LDAP_SUCCESS;
	pam_handle_t *pam_handle;
	struct my_pam_conv_str my_data;
	struct pam_conv my_pam_conv = {pam_conv_func, NULL};
	char *errmsg = NULL; /* free with PR_smprintf_free */
	int locked = 0;

	slapi_pblock_get( pb, SLAPI_BIND_TARGET_SDN, &bindsdn );
	if (NULL == bindsdn) {
		errmsg = PR_smprintf("Null bind dn");
		retcode = LDAP_OPERATIONS_ERROR;
		pam_id.str = NULL; /* initialize pam_id.str */
		goto done; /* skip the pam stuff */
	}
	binddn = slapi_sdn_get_dn(bindsdn);

	if (method == PAMPT_MAP_METHOD_RDN) {
		derive_from_bind_dn(pb, bindsdn, &pam_id);
	} else if (method == PAMPT_MAP_METHOD_ENTRY) {
		derive_from_bind_entry(pb, bindsdn, &pam_id, map_ident_attr, &locked);
	} else {
		init_my_str_buf(&pam_id, binddn);
	}

	if (locked) {
		errmsg = PR_smprintf("Account inactivated. Contact system administrator.");
		retcode = LDAP_UNWILLING_TO_PERFORM; /* user inactivated */
		goto done; /* skip the pam stuff */
	}

	if (!pam_id.str) {
		errmsg = PR_smprintf("Bind DN [%s] is invalid or not found", binddn);
		retcode = LDAP_NO_SUCH_OBJECT; /* user unknown */
		goto done; /* skip the pam stuff */
	}

	/* do the pam stuff */
	my_data.pb = pb;
	my_data.pam_identity = pam_id.str;
	my_pam_conv.appdata_ptr = &my_data;
	slapi_lock_mutex(PAMLock);
	/* from this point on we are in the critical section */
	rc = pam_start(pam_service, pam_id.str, &my_pam_conv, &pam_handle);
	report_pam_error("during pam_start", rc, pam_handle);

	if (rc == PAM_SUCCESS) {
		/* use PAM_SILENT - there is no user interaction at this point */
		rc = pam_authenticate(pam_handle, 0);
		report_pam_error("during pam_authenticate", rc, pam_handle);
		/* check different types of errors here */
		if (rc == PAM_USER_UNKNOWN) {
			errmsg = PR_smprintf("User id [%s] for bind DN [%s] does not exist in PAM",
								 pam_id.str, binddn);
			retcode = LDAP_NO_SUCH_OBJECT; /* user unknown */
		} else if (rc == PAM_AUTH_ERR) {
			errmsg = PR_smprintf("Invalid PAM password for user id [%s], bind DN [%s]",
								 pam_id.str, binddn);
			retcode = LDAP_INVALID_CREDENTIALS; /* invalid creds */
		} else if (rc == PAM_MAXTRIES) {
			errmsg = PR_smprintf("Authentication retry limit exceeded in PAM for "
								 "user id [%s], bind DN [%s]",
								 pam_id.str, binddn);
			if (pw_response_requested) {
				slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_ACCTLOCKED);
			}
			retcode = LDAP_CONSTRAINT_VIOLATION; /* max retries */
		} else if (rc != PAM_SUCCESS) {
			errmsg = PR_smprintf("Unknown PAM error [%s] for user id [%s], bind DN [%s]",
								 pam_strerror(pam_handle, rc), pam_id.str, binddn);
			retcode = LDAP_OPERATIONS_ERROR; /* pam config or network problem */
		}
	}

	/* if user authenticated successfully, see if there is anything we need
	   to report back w.r.t. password or account lockout */
	if (rc == PAM_SUCCESS) {
		rc = pam_acct_mgmt(pam_handle, 0);
		report_pam_error("during pam_acct_mgmt", rc, pam_handle);
		/* check different types of errors here */
		if (rc == PAM_USER_UNKNOWN) {
			errmsg = PR_smprintf("User id [%s] for bind DN [%s] does not exist in PAM",
								 pam_id.str, binddn);
			retcode = LDAP_NO_SUCH_OBJECT; /* user unknown */
		} else if (rc == PAM_AUTH_ERR) {
			errmsg = PR_smprintf("Invalid PAM password for user id [%s], bind DN [%s]",
								 pam_id.str, binddn);
			retcode = LDAP_INVALID_CREDENTIALS; /* invalid creds */
		} else if (rc == PAM_PERM_DENIED) {
			errmsg = PR_smprintf("Access denied for PAM user id [%s], bind DN [%s]"
								 " - see administrator",
								 pam_id.str, binddn);
			if (pw_response_requested) {
				slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_ACCTLOCKED);
			}
			retcode = LDAP_UNWILLING_TO_PERFORM;
		} else if (rc == PAM_ACCT_EXPIRED) {
			errmsg = PR_smprintf("Expired PAM password for user id [%s], bind DN [%s]: "
								 "reset required",
								 pam_id.str, binddn);
			slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
			if (pw_response_requested) {
				slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED);
			}
			retcode = LDAP_INVALID_CREDENTIALS;
		} else if (rc == PAM_NEW_AUTHTOK_REQD) { /* handled same way as ACCT_EXPIRED */
			errmsg = PR_smprintf("Expired PAM password for user id [%s], bind DN [%s]: "
								 "reset required",
								 pam_id.str, binddn);
			slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
			if (pw_response_requested) {
				slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED);
			}
			retcode = LDAP_INVALID_CREDENTIALS;
		} else if (rc != PAM_SUCCESS) {
			errmsg = PR_smprintf("Unknown PAM error [%s] for user id [%s], bind DN [%s]",
								 pam_strerror(pam_handle, rc), pam_id.str, binddn);
			retcode = LDAP_OPERATIONS_ERROR; /* unknown */
		}
	}

	rc = pam_end(pam_handle, rc);
	report_pam_error("during pam_end", rc, pam_handle);
	slapi_unlock_mutex(PAMLock);
	/* not in critical section any more */

done:
	delete_my_str_buf(&pam_id);

	if ((retcode == LDAP_SUCCESS) && (rc != PAM_SUCCESS)) {
		errmsg = PR_smprintf("Unknown PAM error [%d] for user id [%s], bind DN [%s]",
							 rc, pam_id.str, binddn);
		retcode = LDAP_OPERATIONS_ERROR;
	}

	if (retcode != LDAP_SUCCESS) {
		slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
						"%s\n", errmsg);
		if (final_method && !fallback) {
			slapi_send_ldap_result(pb, retcode, NULL, errmsg, 0, NULL);
		}
	}

	if (errmsg) {
		PR_smprintf_free(errmsg);
	}

	return retcode;
}