コード例 #1
0
ファイル: acleffectiverights.c プロジェクト: leto/389-ds
/*
 * Callers should have already allocated *gerstr to hold at least
 * "entryLevelRights: adnvxxx\n".
 */
unsigned long
_ger_get_entry_rights (
	Slapi_PBlock *gerpb,
	Slapi_Entry *e,
	const char *subjectndn,
	char **gerstr,
	size_t *gerstrsize,
	size_t *gerstrcap,
	char **errbuf
	)
{
	unsigned long entryrights = 0;
	Slapi_RDN *rdn = NULL;
	char *rdntype = NULL;
	char *rdnvalue = NULL;

	_append_gerstr(gerstr, gerstrsize, gerstrcap, "entryLevelRights: ", NULL);

	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_entry_rights: SLAPI_ACL_READ\n" );
	if (acl_access_allowed(gerpb, e, "*", NULL, SLAPI_ACL_READ) == LDAP_SUCCESS)
	{
		/* v - view e */
		entryrights |= SLAPI_ACL_READ;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "v", NULL);
	}
	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_entry_rights: SLAPI_ACL_ADD\n" );
	if (acl_access_allowed(gerpb, e, NULL, NULL, SLAPI_ACL_ADD) == LDAP_SUCCESS)
	{
		/* a - add child entry below e */
		entryrights |= SLAPI_ACL_ADD;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "a", NULL);
	}
	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_entry_rights: SLAPI_ACL_DELETE\n" );
	if (acl_access_allowed(gerpb, e, NULL, NULL, SLAPI_ACL_DELETE) == LDAP_SUCCESS)
	{
		/* d - delete e */
		entryrights |= SLAPI_ACL_DELETE;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "d", NULL);
	}
	/*
	 * Some limitation/simplification applied here:
	 * - The modrdn right requires the rights to delete the old rdn and
	 *   the new one. However we have no knowledge of what the new rdn
	 *   is going to be.
	 * - In multi-valued RDN case, we check the right on
	 *   the first rdn type only for now.
	 */
	rdn = slapi_rdn_new_dn ( slapi_entry_get_ndn (e) );
	slapi_rdn_get_first(rdn, &rdntype, &rdnvalue);
	if ( NULL != rdntype ) {
		slapi_log_error (SLAPI_LOG_ACL, plugin_name,
			"_ger_get_entry_rights: SLAPI_ACL_WRITE_DEL & _ADD %s\n", rdntype );
		if (acl_access_allowed(gerpb, e, rdntype, NULL,
				ACLPB_SLAPI_ACL_WRITE_DEL) == LDAP_SUCCESS &&
			acl_access_allowed(gerpb, e, rdntype, NULL,
				ACLPB_SLAPI_ACL_WRITE_ADD) == LDAP_SUCCESS)
		{
			/* n - rename e */
			entryrights |= SLAPI_ACL_WRITE;
			_append_gerstr(gerstr, gerstrsize, gerstrcap, "n", NULL);
		}
	}
	slapi_rdn_free ( &rdn );

	if ( entryrights == 0 )
	{
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL);
	}

	_append_gerstr(gerstr, gerstrsize, gerstrcap, "\n", NULL);

	return entryrights;
}
コード例 #2
0
ファイル: acleffectiverights.c プロジェクト: leto/389-ds
/*
 * *gerstr should point to a heap buffer since it may need
 * to expand dynamically.
 */
unsigned long
_ger_get_attr_rights (
	Slapi_PBlock *gerpb,
	Slapi_Entry *e,
	const char *subjectndn,
	char *type,
	char **gerstr,
	size_t *gerstrsize,
	size_t *gerstrcap,
	int isfirstattr,
	char **errbuf
	)
{
	unsigned long attrrights = 0;

	if (!isfirstattr)
	{
		_append_gerstr(gerstr, gerstrsize, gerstrcap, ", ", NULL);
	}
	_append_gerstr(gerstr, gerstrsize, gerstrcap, type, ":");

	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_attr_rights: SLAPI_ACL_READ %s\n", type );
	if (acl_access_allowed(gerpb, e, type, NULL, SLAPI_ACL_READ) == LDAP_SUCCESS)
	{
		/* r - read the values of type */
		attrrights |= SLAPI_ACL_READ;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "r", NULL);
	}
	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_attr_rights: SLAPI_ACL_SEARCH %s\n", type );
	if (acl_access_allowed(gerpb, e, type, NULL, SLAPI_ACL_SEARCH) == LDAP_SUCCESS)
	{
		/* s - search the values of type */
		attrrights |= SLAPI_ACL_SEARCH;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "s", NULL);
	}
	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_attr_rights: SLAPI_ACL_COMPARE %s\n", type );
	if (acl_access_allowed(gerpb, e, type, NULL, SLAPI_ACL_COMPARE) == LDAP_SUCCESS)
	{
		/* c - compare the values of type */
		attrrights |= SLAPI_ACL_COMPARE;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "c", NULL);
	}
	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_attr_rights: SLAPI_ACL_WRITE_ADD %s\n", type );
	if (acl_access_allowed(gerpb, e, type, NULL, ACLPB_SLAPI_ACL_WRITE_ADD) == LDAP_SUCCESS)
	{
		/* w - add the values of type */
		attrrights |= ACLPB_SLAPI_ACL_WRITE_ADD;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "w", NULL);
	}
	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
		"_ger_get_attr_rights: SLAPI_ACL_WRITE_DEL %s\n", type );
	if (acl_access_allowed(gerpb, e, type, NULL, ACLPB_SLAPI_ACL_WRITE_DEL) == LDAP_SUCCESS)
	{
		/* o - delete the values of type */
		attrrights |= ACLPB_SLAPI_ACL_WRITE_DEL;
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "o", NULL);
	}
	/* If subjectdn has no general write right, check for self write */
	if ( 0 == (attrrights & (ACLPB_SLAPI_ACL_WRITE_DEL | ACLPB_SLAPI_ACL_WRITE_ADD)) )
	{
		struct berval val;

		val.bv_val = (char *)subjectndn;
		val.bv_len = strlen (subjectndn);

		if (acl_access_allowed(gerpb, e, type, &val, ACLPB_SLAPI_ACL_WRITE_ADD) == LDAP_SUCCESS)
		{
			/* W - add self to the attribute */
			attrrights |= ACLPB_SLAPI_ACL_WRITE_ADD;
			_append_gerstr(gerstr, gerstrsize, gerstrcap, "W", NULL);
		}
		if (acl_access_allowed(gerpb, e, type, &val, ACLPB_SLAPI_ACL_WRITE_DEL) == LDAP_SUCCESS)
		{
			/* O - delete self from the attribute */
			attrrights |= ACLPB_SLAPI_ACL_WRITE_DEL;
			_append_gerstr(gerstr, gerstrsize, gerstrcap, "O", NULL);
		}
	}

	if ( attrrights == 0 )
	{
		_append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL);
	}

	return attrrights;
}
コード例 #3
0
ファイル: repl5_total.c プロジェクト: ohamada/389ds
/*
 * Get an annotated value from the BerElement. Returns 0 on
 * success, -1 on failure.
 */
static int
my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
{
	struct berval *attrval = NULL;
	ber_len_t len = -1;
	ber_tag_t tag;
	CSN *csn = NULL;
	char csnstring[CSN_STRSIZE + 1];
	CSNType csntype;
	char *lasti;

	PR_ASSERT(ber && value && deleted);

	if (NULL == ber && NULL == value)
	{
		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 1\n");
		goto loser;
	}

	*value = NULL;

	/* Each value is a sequence */
	if (ber_scanf(ber, "{O", &attrval) == LBER_ERROR)
	{
		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 2\n");
		goto loser;
	}
	/* Allocate and fill in the attribute value */
	if ((*value = slapi_value_new_berval(attrval)) == NULL)
	{
		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 3\n");
		goto loser;
	}

    /* check if this is a deleted value */
    if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
    {
        if (ber_scanf(ber, "b", deleted) == LBER_ERROR)
		{
			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 4\n");
			goto loser;
		}
    }
        
    else /* default is present value */
    {
        *deleted = PR_FALSE;
    }

	/* Read the sequence of CSNs */
    for (tag = ber_first_element(ber, &len, &lasti);
		tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
		tag = ber_next_element(ber, &len, lasti))
	{
		ber_int_t csntype_tmp;
		/* Each CSN is in a sequence that includes a csntype and CSN */
		len = CSN_STRSIZE;
		if (ber_scanf(ber, "{es}", &csntype_tmp, csnstring, &len) == LBER_ERROR)
		{
			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 7 - bval is %s\n", attrval->bv_val);
			goto loser;
		}
		switch (csntype_tmp)
		{
		case CSN_TYPE_VALUE_UPDATED_ON_WIRE:
			csntype = CSN_TYPE_VALUE_UPDATED;
			break;
		case CSN_TYPE_VALUE_DELETED_ON_WIRE:
			csntype = CSN_TYPE_VALUE_DELETED;
			break;
		case CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE:
			csntype = CSN_TYPE_VALUE_DISTINGUISHED;
			break;
		default:
			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: preposterous CSN type "
				"%d received during total update.\n", csntype_tmp);
			goto loser;
		}
		csn = csn_new_by_string(csnstring);
		if (csn == NULL)
		{
			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 8\n");
			goto loser;
		}
		value_add_csn(*value, csntype, csn);
        csn_free (&csn);
	}

	if (ber_scanf(ber, "}") == LBER_ERROR) /* End of annotated attribute value seq */
	{
		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 10\n");
		goto loser;
	}
	
    if (attrval)
        ber_bvfree(attrval); 
	return 0;

loser:
	/* Free any stuff we allocated */
	if (csn)
        csn_free (&csn);
    if (attrval)
        ber_bvfree(attrval); 
    if (value)
    {
        slapi_value_free (value);
    }
   
	return -1;
}
コード例 #4
0
ファイル: acleffectiverights.c プロジェクト: leto/389-ds
static int
_ger_parse_control (
	Slapi_PBlock *pb,
	char **subjectndn,
	int *iscritical,
	char **errbuf
	)
{
	LDAPControl **requestcontrols;
	struct berval *subjectber;
	BerElement *ber;
	size_t subjectndnlen = 0;
	char *orig = NULL;
	char *normed = NULL;

	if (NULL == subjectndn)
	{
		return LDAP_OPERATIONS_ERROR;
	}

	*subjectndn = NULL;

	/*
	 * Get the control
	 */
	slapi_pblock_get ( pb, SLAPI_REQCONTROLS, (void *) &requestcontrols );
	slapi_control_present ( requestcontrols,
							LDAP_CONTROL_GET_EFFECTIVE_RIGHTS,
							&subjectber,
							iscritical );
	if ( subjectber == NULL || subjectber->bv_val == NULL ||
		 subjectber->bv_len == 0 )
	{
		aclutil_str_append ( errbuf, "get-effective-rights: missing subject" );
		slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
		return LDAP_INVALID_SYNTAX;
	}

	if ( strncasecmp ( "dn:", subjectber->bv_val, 3 ) == 0 )
	{
		/*
		 * This is a non-standard support to allow the subject being a plain
		 * or base64 encoding string. Hence users using -J option in
		 * ldapsearch don't have to do BER encoding for the subject.
		 */
		orig = slapi_ch_malloc ( subjectber->bv_len + 1 );
		strncpy ( orig, subjectber->bv_val, subjectber->bv_len );
		*(orig + subjectber->bv_len) = '\0';
	}
	else
	{
		ber = ber_init (subjectber);
		if ( ber == NULL )
		{
			aclutil_str_append ( errbuf, "get-effective-rights: ber_init failed for the subject" );
			slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
			return LDAP_OPERATIONS_ERROR;
		}
		/* "a" means to allocate storage as needed for octet string */
		if ( ber_scanf (ber, "a", &orig) == LBER_ERROR )
		{
			aclutil_str_append ( errbuf, "get-effective-rights: invalid ber tag in the subject" );
			slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
			ber_free ( ber, 1 );
			return LDAP_INVALID_SYNTAX;
		}
		ber_free ( ber, 1 );
	}

	/*
	 * The current implementation limits the subject to authorization ID
	 * (see section 9 of RFC 2829) only. It also only supports the "dnAuthzId"
	 * flavor, which looks like "dn:<DN>" where null <DN> is for anonymous.
	 */
	subjectndnlen = orig ? strlen(orig) : 0;
	if ( NULL == orig || subjectndnlen < 3 || strncasecmp ( "dn:", orig, 3 ) != 0 )
	{
		aclutil_str_append ( errbuf, "get-effective-rights: subject is not dnAuthzId" );
		slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
		slapi_ch_free_string(&orig);
		return LDAP_INVALID_SYNTAX;
	}

	/* memmove is safe for overlapping copy */
	normed = slapi_create_dn_string("%s", orig + 3);
	if (NULL == normed) {
		aclutil_str_append (errbuf, "get-effective-rights: failed to normalize dn: ");
		aclutil_str_append (errbuf, orig);
		slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf);
		slapi_ch_free_string(&orig);
		return LDAP_INVALID_SYNTAX;
	}
	slapi_ch_free_string(&orig);
	*subjectndn = normed;
	slapi_dn_ignore_case(*subjectndn);
	return LDAP_SUCCESS;
}
コード例 #5
0
ファイル: aclgroup.c プロジェクト: leto/389-ds
void
aclg_init_userGroup ( struct acl_pblock *aclpb, const char *n_dn , int got_lock )
{
	aclUserGroup		*u_group = NULL;
	aclUserGroup		*next_ugroup = NULL;
	aclUserGroup		*p_group, *n_group;	
	int found = 0;
		
	/* Check for Anonymous  user */
	if ( n_dn && *n_dn == '\0') return;

	if ( !got_lock ) ACLG_LOCK_GROUPCACHE_WRITE ();
	u_group = aclUserGroups->aclg_first;
	aclpb->aclpb_groupinfo = NULL;

	while ( u_group != NULL ) {
		next_ugroup = u_group->aclug_next;
		if ( aclUserGroups->aclg_signature != u_group->aclug_signature) {
			/*
			 * This means that this usergroup is no longer valid and
			 * this operation so delete this one if no one is using it.
			*/
			
			if ( !u_group->aclug_refcnt ) {
				slapi_log_error( SLAPI_LOG_ACL, plugin_name, 
					"In traversal group deallocation\n" );
				__aclg__delete_userGroup (u_group);								
			}			
		} else {

			/*
			 * Here, u_group is valid--if it matches then take it.
			*/
			if ( slapi_utf8casecmp((ACLUCHP)u_group->aclug_ndn, 
										(ACLUCHP)n_dn ) == 0 ) {
					u_group->aclug_refcnt++;
					aclpb->aclpb_groupinfo = u_group;
					found = 1;
					break;
			}
		}
		u_group = next_ugroup;
	}
	
	/* Move the new one to the top of the queue */
	if ( found )  {
		p_group  = u_group->aclug_prev;
		n_group = u_group->aclug_next;

		if ( p_group )  {
			aclUserGroup	*t_group = NULL;

			p_group->aclug_next = n_group;
			if ( n_group ) n_group->aclug_prev = p_group;

			t_group = aclUserGroups->aclg_first;
			if ( t_group ) t_group->aclug_prev = u_group;

			u_group->aclug_prev = NULL;
			u_group->aclug_next = t_group;
			aclUserGroups->aclg_first = u_group;

			if ( u_group == aclUserGroups->aclg_last )
				aclUserGroups->aclg_last = p_group;
		}
		slapi_log_error(SLAPI_LOG_ACL, plugin_name, "acl_init_userGroup: found in cache for dn:%s\n", n_dn);
	}
	if (!got_lock ) ACLG_ULOCK_GROUPCACHE_WRITE ();
}
コード例 #6
0
ファイル: repl5_agmtlist.c プロジェクト: ohamada/389ds
static int
agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *e,
	int *returncode, char *returntext, void *arg)
{
	int i;
	Slapi_DN *sdn = NULL;
	int start_initialize = 0, stop_initialize = 0, cancel_initialize = 0;
    int update_the_schedule = 0;	/* do we need to update the repl sched? */
	Repl_Agmt *agmt = NULL;
	LDAPMod **mods;
    char buff [SLAPI_DSE_RETURNTEXT_SIZE];
    char *errortext = returntext ? returntext : buff;
    int rc = SLAPI_DSE_CALLBACK_OK;
    Slapi_Operation *op;
    void *identity;

    *returncode = LDAP_SUCCESS;

     /* just let internal operations originated from replication plugin to go through */
    slapi_pblock_get (pb, SLAPI_OPERATION, &op);
    slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);                

    if (operation_is_flag_set(op, OP_FLAG_INTERNAL) &&
        (identity == repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION)))
    {
        goto done;
    }

    slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
    if (NULL == sdn) {
        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, 
                        "agmtlist_modify_callback: NULL target dn\n");
        goto done;
    }
	agmt = agmtlist_get_by_agmt_name(sdn);
	if (NULL == agmt)
	{
		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmtlist_modify_callback: received "
			"a modification for unknown replication agreement \"%s\"\n", 
			slapi_sdn_get_dn(sdn));
		goto done;
	}

	slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
	for (i = 0; NULL != mods && NULL != mods[i]; i++)
	{
		if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaInitialize))
		{
            /* we don't allow delete attribute operations unless it was issued by
               the replication plugin - handled above */
            if (mods[i]->mod_op & LDAP_MOD_DELETE)
            {
                if(strcasecmp (mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified) == 0){
                    /* allow the deletion of cleanallruv agmt attr */
                    continue;
                }

                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "deletion of %s attribute is not allowed\n", type_nsds5ReplicaInitialize);	
                *returncode = LDAP_UNWILLING_TO_PERFORM;
                rc = SLAPI_DSE_CALLBACK_ERROR;
                break;
            }
            else
            {
                char *val;

                if (mods[i]->mod_bvalues && mods[i]->mod_bvalues[0])
                    val = slapi_berval_get_string_copy (mods[i]->mod_bvalues[0]);
                else
                {
                    slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "no value provided for %s attribute\n", type_nsds5ReplicaInitialize);
                    *returncode = LDAP_UNWILLING_TO_PERFORM;
                    rc = SLAPI_DSE_CALLBACK_ERROR;
                    break;   
                }

			    /* Start replica initialization */
                if (val == NULL)
                {
                    PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "No value supplied for attr (%s)", mods[i]->mod_type);
                    slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: %s\n",
                                    errortext);	  
                    *returncode = LDAP_UNWILLING_TO_PERFORM;
                    rc = SLAPI_DSE_CALLBACK_ERROR;
                    break;
                }
            
                if (strcasecmp (val, "start") == 0)
                {                        
                    start_initialize = 1;
                }
                else if (strcasecmp (val, "stop") == 0)
                {
                    stop_initialize = 1;
                }
                else if (strcasecmp (val, "cancel") == 0)
                {
                    cancel_initialize = 1;
                }
                else
                {
                    PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid value (%s) value supplied for attr (%s)", 
                             val, mods[i]->mod_type);
                    slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: %s\n", errortext);
                }
                slapi_ch_free ((void**)&val);
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicaUpdateSchedule))
		{
			/*
			 * Request to update the replication schedule.  Set a flag so
			 * we know to update the schedule later.
			 */
			update_the_schedule = 1;
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicaCredentials))
		{
			/* New replica credentials */
			if (agmt_set_credentials_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update credentials for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicaTimeout))
		{
			/* New replica timeout */
			if (agmt_set_timeout_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update timeout for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicaBusyWaitTime))
		{
			/* New replica busywaittime */
			if (agmt_set_busywaittime_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update busy wait time for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicaSessionPauseTime))
		{
			/* New replica pausetime */
			if (agmt_set_pausetime_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update session pause time for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicaBindDN))
		{
			/* New replica Bind DN */
			if (agmt_set_binddn_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update bind DN for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
		                                     type_nsds5ReplicaPort))
		{
			/* New replica port */
			if (agmt_set_port_from_entry(agmt, e) != 0)
			{
				slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
				                "agmtlist_modify_callback: " 
				                "failed to update port for agreement %s\n",
				                agmt_get_long_name(agmt));	
				*returncode = LDAP_OPERATIONS_ERROR;
				rc = SLAPI_DSE_CALLBACK_ERROR;
			}
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5TransportInfo))
		{
			/* New Transport info */
			if (agmt_set_transportinfo_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update transport info for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicaBindMethod))
		{
			if (agmt_set_bind_method_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update bind method for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicatedAttributeList))
		{
			char **denied_attrs = NULL;
			/* New set of excluded attributes */
			if (agmt_set_replicated_attributes_from_entry(agmt, e) != 0)
            {
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                                "failed to update replicated attributes for agreement %s\n",
                                agmt_get_long_name(agmt));	
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
			/* Check that there are no verboten attributes in the exclude list */
			denied_attrs = agmt_validate_replicated_attributes(agmt, 0 /* incremental */);
			if (denied_attrs)
			{
				/* Report the error to the client */
				PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "attempt to exclude an illegal attribute in a fractional agreement");
				slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                            "attempt to exclude an illegal attribute in a fractional agreement\n");

				*returncode = LDAP_UNWILLING_TO_PERFORM;
				rc = SLAPI_DSE_CALLBACK_ERROR;
				/* Free the deny list if we got one */
				slapi_ch_array_free(denied_attrs);
				break;
			}
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
					type_nsds5ReplicatedAttributeListTotal))
		{
			char **denied_attrs = NULL;
			/* New set of excluded attributes */
			if (agmt_set_replicated_attributes_total_from_entry(agmt, e) != 0)
			{
				slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
								"failed to update total update replicated attributes for agreement %s\n",
								agmt_get_long_name(agmt));
				*returncode = LDAP_OPERATIONS_ERROR;
				rc = SLAPI_DSE_CALLBACK_ERROR;
			}
			/* Check that there are no verboten attributes in the exclude list */
			denied_attrs = agmt_validate_replicated_attributes(agmt, 1 /* total */);
			if (denied_attrs)
			{
				/* Report the error to the client */
				PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "attempt to exclude an illegal total update "
						"attribute in a fractional agreement");
				slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
						"attempt to exclude an illegal total update attribute in a fractional agreement\n");

				*returncode = LDAP_UNWILLING_TO_PERFORM;
				rc = SLAPI_DSE_CALLBACK_ERROR;
				/* Free the deny list if we got one */
				slapi_ch_array_free(denied_attrs);
				break;
			}
		}
		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
											 "nsds5debugreplicatimeout"))
		{
			char *val = slapi_entry_attr_get_charptr(e, "nsds5debugreplicatimeout");
			repl5_set_debug_timeout(val);
			slapi_ch_free_string(&val);
		}
        else if (strcasecmp (mods[i]->mod_type, "modifytimestamp") == 0 ||
                 strcasecmp (mods[i]->mod_type, "modifiersname") == 0 ||
                 strcasecmp (mods[i]->mod_type, "description") == 0)
        {
            /* ignore modifier's name and timestamp attributes and the description. */
            continue;
        }
        else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaEnabled))
        {
            if(agmt_set_enabled_from_entry(agmt, e, returntext) != 0){
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
                    "failed to set replica agmt state \"enabled/disabled\" for %s\n",agmt_get_long_name(agmt));
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
        }
        else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaStripAttrs))
        {
            if(agmt_set_attrs_to_strip(agmt, e) != 0){
                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: "
                    "failed to set replica agmt attributes to strip for %s\n",agmt_get_long_name(agmt));
                *returncode = LDAP_OPERATIONS_ERROR;
                rc = SLAPI_DSE_CALLBACK_ERROR;
            }
        }
        else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e))
        {
            slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                            "modification of %s attribute is not allowed\n", mods[i]->mod_type);
            *returncode = LDAP_UNWILLING_TO_PERFORM;
            rc = SLAPI_DSE_CALLBACK_ERROR;
            break;
        }
	}

	if (stop_initialize)
	{
        agmt_stop (agmt);
    }
    else if (start_initialize)
    {
        if (agmt_initialize_replica(agmt) != 0) {
            /* The suffix/repl agmt is disabled */
            agmt_set_last_init_status(agmt, 0, NSDS50_REPL_DISABLED, NULL);
            if(agmt_is_enabled(agmt)){
                PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Suffix is disabled");
            } else {
                PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replication agreement is disabled");
            }
            *returncode = LDAP_UNWILLING_TO_PERFORM;
            rc = SLAPI_DSE_CALLBACK_ERROR;
        }
    }
    else if (cancel_initialize)
    {
        agmt_replica_init_done(agmt);
    }

	if (update_the_schedule) 
    {
		if (agmt_set_schedule_from_entry(agmt, e) != 0)
        {
            slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
                            "failed to update replication schedule for agreement %s\n",
                            agmt_get_long_name(agmt));	
            *returncode = LDAP_OPERATIONS_ERROR;
            rc = SLAPI_DSE_CALLBACK_ERROR;
        }
	}

done:
	if (NULL != agmt)
	{
		agmtlist_release_agmt(agmt);
	}

	return rc;
}
コード例 #7
0
ファイル: fixup_task.c プロジェクト: leto/389-ds
/*
 * Function Implementations
 */
int
linked_attrs_fixup_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
                Slapi_Entry *eAfter, int *returncode,
                char *returntext, void *arg)
{
	PRThread *thread = NULL;
	int rv = SLAPI_DSE_CALLBACK_OK;
	task_data *mytaskdata = NULL;
	Slapi_Task *task = NULL;
	const char *linkdn = NULL;
	char *bind_dn;

	*returncode = LDAP_SUCCESS;

	/* make sure the plugin is not closed */
	if(!linked_attrs_is_started()){
		*returncode = LDAP_OPERATIONS_ERROR;
		rv = SLAPI_DSE_CALLBACK_ERROR;
		goto out;
	}

	/* get arg(s) */
	linkdn = fetch_attr(e, "linkdn", 0);

	/* setup our task data */
	slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &bind_dn);
	mytaskdata = (task_data*)slapi_ch_calloc(1, sizeof(task_data));
	if (mytaskdata == NULL) {
		*returncode = LDAP_OPERATIONS_ERROR;
		rv = SLAPI_DSE_CALLBACK_ERROR;
		goto out;
	}

	if (linkdn) {
	    mytaskdata->linkdn = slapi_dn_normalize(slapi_ch_strdup(linkdn));
	}
	mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);

	/* allocate new task now */
	task = slapi_new_task(slapi_entry_get_ndn(e));

	/* register our destructor for cleaning up our private data */
	slapi_task_set_destructor_fn(task, linked_attrs_fixup_task_destructor);

	/* Stash a pointer to our data in the task */
	slapi_task_set_data(task, mytaskdata);

	/* start the sample task as a separate thread */
	thread = PR_CreateThread(PR_USER_THREAD, linked_attrs_fixup_task_thread,
		(void *)task, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
		PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
	if (thread == NULL) {
		slapi_log_error( SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
			"unable to create task thread!\n");
		*returncode = LDAP_OPERATIONS_ERROR;
		rv = SLAPI_DSE_CALLBACK_ERROR;
		slapi_task_finish(task, *returncode);
	} else {
		rv = SLAPI_DSE_CALLBACK_OK;
	}

out:
	return rv;
}
コード例 #8
0
ファイル: retrocl_create.c プロジェクト: leto/389-ds
/*
 * Function: retrocl_create_config
 *
 * Returns: LDAP_
 * 
 * Arguments: none
 *
 * Description:
 * This function is called if there was no mapping tree node or backend for 
 * cn=changelog.
 */
int retrocl_create_config(void)
{
    Slapi_PBlock *pb = NULL;
    Slapi_Entry *e;
    struct berval *vals[2];
    struct berval val;
    int rc;
    char *mappingtree_dn = NULL;

    vals[0] = &val;
    vals[1] = NULL; 

    /* Assume the mapping tree node is missing.  It doesn't hurt to 
     * attempt to add it if it already exists.  You will see a warning
     * in the errors file when the referenced backend does not exist.
     */
    e = slapi_entry_alloc();
    /* This function converts the old DN style to the new one. */
    mappingtree_dn = slapi_create_dn_string("%s", RETROCL_MAPPINGTREE_DN);
    if (NULL == mappingtree_dn) {
        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
                         "retrocl_create_config: failed to normalize "
                         "mappingtree dn %s\n", RETROCL_MAPPINGTREE_DN);
        return LDAP_PARAM_ERROR;
    }
    slapi_entry_set_dn(e, mappingtree_dn); /* mappingtree_dn is consumed */
    
    /* Set the objectclass attribute */
    val.bv_val = "top";
    val.bv_len = 3;
    slapi_entry_add_values( e, "objectclass", vals );

    
    /* Set the objectclass attribute */
    val.bv_val = "extensibleObject";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "objectclass", vals );

    /* Set the objectclass attribute */
    val.bv_val = "nsMappingTree";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "objectclass", vals );

    val.bv_val = "backend";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsslapd-state", vals );

    val.bv_val = RETROCL_CHANGELOG_DN;
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "cn", vals );

    val.bv_val = "changelog";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsslapd-backend", vals );
    
    pb = slapi_pblock_new ();
    slapi_add_entry_internal_set_pb( pb, e, NULL /* controls */, 
				     g_plg_identity[PLUGIN_RETROCL], 
				     0 /* actions */ );
    slapi_add_internal_pb (pb);
    slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_RESULT, &rc );
    slapi_pblock_destroy(pb);
    
    if (rc == 0) {
        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
			 "created changelog mapping tree node\n");
    } else if (rc == LDAP_ALREADY_EXISTS) {
        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
			 "changelog mapping tree node already existed\n");
    } else {
        slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME, "cn=\"cn=changelog\",cn=mapping tree,cn=config could not be created (%d)\n", rc);
	return rc;
    }

    retrocl_be_changelog = slapi_be_select_by_instance_name("changelog");

    if (retrocl_be_changelog == NULL) {
        /* This is not the nsslapd-changelogdir from cn=changelog4,cn=config */
        char *bedir;

	bedir = retrocl_get_config_str(CONFIG_CHANGELOG_DIRECTORY_ATTRIBUTE);
	
	if (bedir == NULL) {
	    /* none specified */
	}

	rc = retrocl_create_be(bedir);
	slapi_ch_free ((void **)&bedir);
	if (rc != LDAP_SUCCESS && rc != LDAP_ALREADY_EXISTS) {
	    return rc;
	}

	retrocl_be_changelog = slapi_be_select_by_instance_name("changelog");
    }

    return LDAP_SUCCESS;
}
コード例 #9
0
ファイル: fixup_task.c プロジェクト: leto/389-ds
static void
linked_attrs_fixup_task_thread(void *arg)
{
	int rc = 0;
	Slapi_Task *task = (Slapi_Task *)arg;
	task_data *td = NULL;
	PRCList *main_config = NULL;
	int found_config = 0;

	/* Fetch our task data from the task */
	td = (task_data *)slapi_task_get_data(task);

	/* init and set the bind dn in the thread data */
	slapi_td_set_dn(slapi_ch_strdup(td->bind_dn));

	/* Log started message. */
	slapi_task_begin(task, 1);
	slapi_task_log_notice(task, "Linked attributes fixup task starting (link dn: \"%s\") ...\n",
	                      td->linkdn ? td->linkdn : "");
	slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
	                "Syntax validate task starting (link dn: \"%s\") ...\n",
                        td->linkdn ? td->linkdn : "");

    linked_attrs_read_lock();
    main_config = linked_attrs_get_config();
    if (!PR_CLIST_IS_EMPTY(main_config)) {
       struct configEntry *config_entry = NULL;
       PRCList *list = PR_LIST_HEAD(main_config);

        while (list != main_config) {
            config_entry = (struct configEntry *) list;

            /* See if this is the requested config and fix up if so. */
            if (td->linkdn) {
                if (strcasecmp(td->linkdn, config_entry->dn) == 0) {
                    found_config = 1;
                    slapi_task_log_notice(task, "Fixing up linked attribute pair (%s)\n",
                         config_entry->dn);
                    slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
                         "Fixing up linked attribute pair (%s)\n", config_entry->dn);

                    linked_attrs_fixup_links(config_entry);
                    break;
                }
            } else {
                /* No config DN was supplied, so fix up all configured links. */
                slapi_task_log_notice(task, "Fixing up linked attribute pair (%s)\n",
                        config_entry->dn);
                slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
                       "Fixing up linked attribute pair (%s)\n", config_entry->dn);

                linked_attrs_fixup_links(config_entry);
            }

            list = PR_NEXT_LINK(list);
        }
    }

    /* Log a message if we didn't find the requested attribute pair. */
    if (td->linkdn && !found_config) {
        slapi_task_log_notice(task, "Requested link config DN not found (%s)\n",
                td->linkdn);
        slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
                "Requested link config DN not found (%s)\n", td->linkdn);
    }

    linked_attrs_unlock();

	/* Log finished message. */
	slapi_task_log_notice(task, "Linked attributes fixup task complete.\n");
	slapi_task_log_status(task, "Linked attributes fixup task complete.\n");
	slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM, "Linked attributes fixup task complete.\n");
	slapi_task_inc_progress(task);

	/* this will queue the destruction of the task */
	slapi_task_finish(task, rc);
}
コード例 #10
0
ファイル: fixup_task.c プロジェクト: leto/389-ds
static int
linked_attrs_add_backlinks_callback(Slapi_Entry *e, void *callback_data)
{
    int rc = 0;
    char *linkdn = slapi_entry_get_dn(e);
    struct configEntry *config = (struct configEntry *)callback_data;
    Slapi_PBlock *pb = slapi_pblock_new();
    int i = 0;
    char **targets = NULL;
    char *val[2];
    LDAPMod mod;
    LDAPMod *mods[2];

    /* Setup the modify operation.  Only the target will
     * change, so we only need to do this once. */
    val[0] = linkdn;
    val[1] = 0;

    mod.mod_op = LDAP_MOD_ADD;
    mod.mod_type = config->managedtype;
    mod.mod_values = val;

    mods[0] = &mod;
    mods[1] = 0;

    targets = slapi_entry_attr_get_charray(e, config->linktype);
    for (i = 0; targets && targets[i]; ++i) {
        char *targetdn = (char *)targets[i];
        int perform_update = 0;
        Slapi_DN *targetsdn = NULL;

        if (slapi_is_shutting_down()) {
            rc = -1;
            goto done;
        }

        targetsdn = slapi_sdn_new_normdn_byref(targetdn);
        if (config->scope) {
            /* Check if the target is within the scope. */
            perform_update = slapi_dn_issuffix(targetdn, config->scope);
        } else {
            /* Find out the root suffix that the linkdn is in
             * and see if the target is in the same backend. */
            Slapi_Backend *be = NULL;
            Slapi_DN *linksdn = slapi_sdn_new_normdn_byref(linkdn);

            if ((be = slapi_be_select(linksdn))) {
                perform_update = slapi_sdn_issuffix(targetsdn, slapi_be_getsuffix(be, 0));
            }

            slapi_sdn_free(&linksdn);
        }

        if (perform_update) {
            slapi_log_error(SLAPI_LOG_PLUGIN, LINK_PLUGIN_SUBSYSTEM,
                            "Adding backpointer (%s) in entry (%s)\n",
                            linkdn, targetdn);

            /* Perform the modify operation. */
            slapi_modify_internal_set_pb_ext(pb, targetsdn, mods, 0, 0,
                                             linked_attrs_get_plugin_id(), 0);
            slapi_modify_internal_pb(pb);

            /* Initialize the pblock so we can reuse it. */
            slapi_pblock_init(pb);
        }
        slapi_sdn_free(&targetsdn);
    }

done:
    slapi_ch_array_free(targets);
    slapi_pblock_destroy(pb);

    return rc;
}
コード例 #11
0
ファイル: windows_private.c プロジェクト: leto/389-ds
static int
windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e)
{
	char *tmpstr = NULL;
	int retval = 0;
	
	if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsReplicaArea))
	{
		tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsReplicaArea);
		if (NULL != tmpstr)
		{
			windows_private_set_windows_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
		}
		retval = 1;
	}
	if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7DirectoryReplicaArea))
	{
		tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7DirectoryReplicaArea); 
		if (NULL != tmpstr)
		{
			windows_private_set_directory_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
		}
		retval = 1;
	}
	if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7CreateNewUsers))
	{
		tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7CreateNewUsers); 
		if (NULL != tmpstr && true_value_from_string(tmpstr))
		{
			windows_private_set_create_users(ra, PR_TRUE);
		}
		else
		{
			windows_private_set_create_users(ra, PR_FALSE);
		}
		retval = 1;
		slapi_ch_free((void**)&tmpstr);
	}
	if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7CreateNewGroups))
	{
		tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7CreateNewGroups); 
		if (NULL != tmpstr && true_value_from_string(tmpstr))
		{
			windows_private_set_create_groups(ra, PR_TRUE);
		}
		else
		{
			windows_private_set_create_groups(ra, PR_FALSE);
		}
		retval = 1;
		slapi_ch_free((void**)&tmpstr);
	}
	if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsDomain))
	{
		tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsDomain); 
		if (NULL != tmpstr)
		{
			windows_private_set_windows_domain(ra,tmpstr);
		}
		/* No need to free tmpstr because it was aliased by the call above */
		tmpstr = NULL;
		retval = 1;
	}
	if (type == NULL || slapi_attr_types_equivalent(type,type_winSyncInterval))
	{
		tmpstr = slapi_entry_attr_get_charptr(e, type_winSyncInterval); 
		if (NULL != tmpstr)
		{
			windows_private_set_sync_interval(ra,tmpstr);
		}
		slapi_ch_free_string(&tmpstr);
		retval = 1;
	}
	if (type == NULL || slapi_attr_types_equivalent(type,type_oneWaySync))
	{
		tmpstr = slapi_entry_attr_get_charptr(e, type_oneWaySync);
		if (NULL != tmpstr)
		{
			if (strcasecmp(tmpstr, "fromWindows") == 0) {
				windows_private_set_one_way(ra, ONE_WAY_SYNC_FROM_AD);
			} else if (strcasecmp(tmpstr, "toWindows") == 0) {
				windows_private_set_one_way(ra, ONE_WAY_SYNC_TO_AD);
			} else {
				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
					"Ignoring illegal setting for %s attribute in replication "
					"agreement \"%s\".  Valid values are \"toWindows\" or "
					"\"fromWindows\".\n", type_oneWaySync, slapi_entry_get_dn(e));
				windows_private_set_one_way(ra, ONE_WAY_SYNC_DISABLED);
			}
		}
		else
		{
			windows_private_set_one_way(ra, ONE_WAY_SYNC_DISABLED);
		}
		slapi_ch_free((void**)&tmpstr);
		retval = 1;
	}
	return retval;
}
コード例 #12
0
ファイル: repl5_total.c プロジェクト: ohamada/389ds
/*
 * This plugin entry point is called whenever an NSDS50ReplicationEntry
 * extended operation is received.
 */
int
multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock  *pb)
{
	int rc;
	Slapi_Entry *e = NULL;
    Slapi_Connection *conn = NULL;
	PRUint64 connid = 0;
	int opid = 0;
	
	slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
	slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);

	/* Decode the extended operation */
	rc = decode_total_update_extop(pb, &e);

	if (0 == rc)
	{
#ifdef notdef
		/*
		 * Just spew LDIF so we're sure we got it right. Later we'll firehose
		 * this into the database import code
		 */
		int len;
		char *str = slapi_entry2str_with_options(e, &len,SLAPI_DUMP_UNIQUEID);
		puts(str);
		free(str);
#endif

       rc = slapi_import_entry (pb, e); 
       /* slapi_import_entry returns an LDAP error in case of a
        * problem.  If there's a problem, it's our responsibility
        * to free the slapi_entry that we're trying to import.
        */
       if (rc != LDAP_SUCCESS)
	   {
		   const char *dn = slapi_entry_get_dn_const(e);
		   slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
						   "Error %d: could not import entry dn %s "
						   "for total update operation conn=%" NSPRIu64 " op=%d\n",
						   rc, dn, connid, opid);
		   rc = -1;
	   }
        
	}
	else
	{
		slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
						"Error %d: could not decode the total update extop "
						"for total update operation conn=%" NSPRIu64 " op=%d\n",
						rc, connid, opid);
	}
   
    if (rc != 0)
    {
        /* just disconnect from the supplier. bulk import is stopped when
           connection object is destroyed */
        slapi_pblock_get (pb, SLAPI_CONNECTION, &conn);
        if (conn)
        {
            slapi_disconnect_server(conn);
        }

        /* cleanup */
        if (e)
        {
            slapi_entry_free (e);
        }
    }

	return rc;
}
コード例 #13
0
ファイル: repl5_total.c プロジェクト: ohamada/389ds
/*
 * Extract the payload from a total update extended operation,
 * decode it, and produce a Slapi_Entry structure representing a new
 * entry to be added to the local database.
 */
static int
decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
{
	BerElement *tmp_bere = NULL;
	Slapi_Entry *e = NULL;
	Slapi_Attr *attr = NULL;
	char *str = NULL;
	struct berval *extop_value = NULL;
	char *extop_oid = NULL;
	ber_len_t len;
	char *lasto;
	ber_tag_t tag;
	int rc;
	PRBool deleted;
	
	PR_ASSERT(NULL != pb);
	PR_ASSERT(NULL != ep);

	slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
	slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);

	if ((NULL == extop_oid) || 
		((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) && 
		 (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) ||
		!BV_HAS_DATA(extop_value))
	{
		/* Bogus */
		goto loser;
	}

	if ((tmp_bere = ber_init(extop_value)) == NULL)
	{
		goto loser;
	}

	if ((e = slapi_entry_alloc()) == NULL)
	{
		goto loser;
	}

	if (ber_scanf(tmp_bere, "{") == LBER_ERROR) /* Begin outer sequence */
	{
		goto loser;
	}

	/* The entry's uniqueid is first */
	if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
	{
		goto loser;
	}
	slapi_entry_set_uniqueid(e, str);
	str = NULL;	/* Slapi_Entry now owns the uniqueid */

	/* The entry's DN is next */
	if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
	{
		goto loser;
	}
	slapi_entry_set_dn(e, str);
	str = NULL; /* Slapi_Entry now owns the dn */

	/* Get the attributes */
	for ( tag = ber_first_element( tmp_bere, &len, &lasto );
		tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
		tag = ber_next_element( tmp_bere, &len, lasto ) )
	{

        if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0)
        {
            goto loser;
        }
		
	    /* Add the attribute to the entry */
        if (deleted)
            entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */
        else
		    entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */
        attr = NULL;
	}

    if (ber_scanf(tmp_bere, "}") == LBER_ERROR) /* End sequence for this entry */
	{
		goto loser;
	}

	/* Check for ldapsubentries and tombstone entries to set flags properly */
	slapi_entry_attr_find(e, "objectclass", &attr);
	if (attr != NULL) {
		struct berval bv;
		bv.bv_val = "ldapsubentry";
		bv.bv_len = strlen(bv.bv_val);
		if (slapi_attr_value_find(attr, &bv) == 0) {
			slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY);
		}
		bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE;
		bv.bv_len = strlen(bv.bv_val);
		if (slapi_attr_value_find(attr, &bv) == 0) {
			slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE);
		}
	}
	
	/* If we get here, the entry is properly constructed. Return it. */

	rc = 0;
	*ep = e;
	goto free_and_return;

loser:
	rc = -1;
	/* slapi_ch_free accepts NULL pointer */
	slapi_ch_free((void **)&str);

    if (attr != NULL)
    {
        slapi_attr_free (&attr);
    }
    
    if (NULL != e)
    {
        slapi_entry_free (e);
    }
	*ep = NULL;
	slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: could not decode extended "
		"operation containing entry for total update.\n");

free_and_return:
    if (NULL != tmp_bere)
	{
		ber_free(tmp_bere, 1); 
		tmp_bere = NULL;
	}
	return rc;
}
コード例 #14
0
ファイル: acleffectiverights.c プロジェクト: leto/389-ds
int
_ger_generate_template_entry (
	Slapi_PBlock    *pb
	)
{
	Slapi_Entry	*e = NULL;
	char **gerattrs = NULL;
	char **attrs = NULL;
	char **allowedattrs = NULL;
	char *templateentry = NULL;
	char *object = NULL;
	char *superior = NULL;
	char *p = NULL;
	const char *dn = NULL;
	Slapi_DN *sdn = NULL;
	char *dntype = NULL;
	int siz = 0;
	int len = 0;
	int i = 0;
	int notfirst = 0;
	int rc = LDAP_SUCCESS;

	slapi_pblock_get( pb, SLAPI_SEARCH_GERATTRS, &gerattrs );
	if (NULL == gerattrs)
	{
		slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
						"Objectclass info is expected "
						"in the attr list, e.g., \"*@person\"\n");
		rc = LDAP_SUCCESS;
		goto bailout;
	}
	for (i = 0; gerattrs && gerattrs[i]; i++)
	{
		object = strchr(gerattrs[i], '@');
		if (NULL != object && '\0' != *(++object))
		{
			break;
		}
	}
	if (NULL == object)
	{
		rc = LDAP_SUCCESS;	/* no objectclass info; ok to return */
		goto bailout;
	}
	/* 
	 * Either @objectclass or @objectclass:dntype is accepted.
	 * If @objectclass, the first MUST attributetype (or the first MAY
	 * attributetype if MUST does not exist) is used for the attribute
	 * type in the leaf RDN.
	 * If @objectclass:dntype, dntype is used for the attribute type in the
	 * leaf RDN.
	 */
	dntype = strchr(object, ':');
	if (dntype) { /* @objectclasse:dntype */
		*dntype++ = '\0';
	}

	attrs = slapi_schema_list_objectclass_attributes(
						(const char *)object, SLAPI_OC_FLAG_REQUIRED);
	allowedattrs = slapi_schema_list_objectclass_attributes(
						(const char *)object, SLAPI_OC_FLAG_ALLOWED);
	charray_merge(&attrs, allowedattrs, 0 /* no copy */);
	slapi_ch_free((void **)&allowedattrs); /* free just allowedattrs */
	if (NULL == attrs) {
		rc = LDAP_SUCCESS;	/* bogus objectclass info; ok to return */
		goto bailout;
	}
	for (i = 0; attrs[i]; i++)
	{
		if (0 == strcasecmp(attrs[i], "objectclass"))
		{
			/* <*attrp>: <object>\n\0 */
			siz += strlen(attrs[i]) + 4 + strlen(object);
		}
		else
		{
			/* <*attrp>: (template_attribute)\n\0 */
			siz += strlen(attrs[i]) + 4 + 20;
		}
	}
	/* get the target dn where the template entry is located */
	slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
	dn = slapi_sdn_get_dn(sdn);
	if (dn)
	{
		/* dn: <attr>=<template_name>,<dn>\n\0 */
		if (dntype) {
			siz += strlen(dntype) + 30 + strlen(object) + strlen(dn);
		} else {
			siz += strlen(attrs[0]) + 30 + strlen(object) + strlen(dn);
		}
	}
	else
	{
		/* dn: <attr>=<template_name>\n\0 */
		if (dntype) {
			siz += strlen(dntype) + 30 + strlen(object);
		} else {
			siz += strlen(attrs[0]) + 30 + strlen(object);
		}
	}
	templateentry = (char *)slapi_ch_malloc(siz);
	if (NULL != dn && strlen(dn) > 0)
	{
		PR_snprintf(templateentry, siz,
		            "dn: %s=template_%s_objectclass,%s\n",
		            dntype?dntype:attrs[0], object, dn);
	}
	else
	{
		PR_snprintf(templateentry, siz,
		            "dn: %s=template_%s_objectclass\n",
		            dntype?dntype:attrs[0], object);
	}
	for (--i; i >= 0; i--)
	{
		len = strlen(templateentry);
		p = templateentry + len;
		if (0 == strcasecmp(attrs[i], "objectclass"))
		{
			PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object);
		}
		else
		{
			PR_snprintf(p, siz - len, "%s: (template_attribute)\n", attrs[i]);
		}
	}
	charray_free(attrs);

	while ((superior = slapi_schema_get_superior_name(object)) &&
			(0 != strcasecmp(superior, "top")))
	{
		if (notfirst)
		{
			slapi_ch_free_string(&object);
		}
		notfirst = 1;
		object = superior;
		attrs = slapi_schema_list_objectclass_attributes(
						(const char *)superior, SLAPI_OC_FLAG_REQUIRED);
		for (i = 0; attrs && attrs[i]; i++)
		{
			if (0 == strcasecmp(attrs[i], "objectclass"))
			{
				/* <*attrp>: <object>\n\0 */
				siz += strlen(attrs[i]) + 4 + strlen(object);
			}
		}
		templateentry = (char *)slapi_ch_realloc(templateentry, siz);
		for (--i; i >= 0; i--)
		{
			len = strlen(templateentry);
			p = templateentry + len;
			if (0 == strcasecmp(attrs[i], "objectclass"))
			{
				PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object);
			}
		}
		charray_free(attrs);
	}
	if (notfirst)
	{
		slapi_ch_free_string(&object);
	}
	slapi_ch_free_string(&superior);
	siz += 18; /* objectclass: top\n\0 */
	len = strlen(templateentry);
	templateentry = (char *)slapi_ch_realloc(templateentry, siz);
	p = templateentry + len;
	PR_snprintf(p, siz - len, "objectclass: top\n");

	e = slapi_str2entry(templateentry, SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF);
	/* set the template entry to send the result to clients */
	slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, e);
bailout:
	slapi_ch_free_string(&templateentry);
	return rc;
}
コード例 #15
0
ファイル: topology_init.c プロジェクト: borland667/freeipa
int ipa_topo_init(Slapi_PBlock *pb)
{
    int rc = 0;
    void *ipa_topo_plugin_identity = NULL;

    slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
                    "--> ipa_topo_init\n");

    /**
     * Store the plugin identity for later use.
     * Used for internal operations
     */

    slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &ipa_topo_plugin_identity);
    ipa_topo_set_plugin_id(ipa_topo_plugin_identity);

    if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) != 0
        || slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *)ipa_topo_start) != 0
        || slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, (void *)ipa_topo_close) != 0
        || slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) != 0) {
        slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
                        "ipa_topo_init: failed to register plugin\n");
        rc = 1;
    }

    if (rc == 0) {
        char *plugin_type = "bepreoperation";
        if (slapi_register_plugin(plugin_type, 1, "ipa_topo_init",
                                  ipa_topo_preop_init, IPA_TOPO_PREOP_DESC,
                                  NULL, ipa_topo_get_plugin_id())) {
            slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
                            "ipa_topo_init: failed to register preop plugin\n");
            rc = 1;
        }
    }

    if (rc == 0) {
        char *plugin_type = "postoperation";
        if (slapi_register_plugin(plugin_type, 1, "ipa_topo_init",
                                  ipa_topo_postop_init, IPA_TOPO_POSTOP_DESC,
                                  NULL, ipa_topo_get_plugin_id())) {
            slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
                            "ipa_topo_init: failed to register postop plugin\n");
            rc = 1;
        }
    }
    if (rc == 0) {
        char *plugin_type = "internalpostoperation";
        if (slapi_register_plugin(plugin_type, 1, "ipa_topo_internal_init",
                                  ipa_topo_internal_postop_init,
                                  IPA_TOPO_INTERNAL_POSTOP_DESC,
                                  NULL, ipa_topo_get_plugin_id())) {
            slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
                            "ipa_topo_init: failed to register internal postop plugin\n");
            rc = 1;
        }
    }

    slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
                    "<-- ipa_topo_init\n");
    return(rc);
}
コード例 #16
0
ファイル: acleffectiverights.c プロジェクト: leto/389-ds
static int
_ger_g_permission_granted (
	Slapi_PBlock *pb,
	Slapi_Entry *e,
	const char *subjectdn,
	char **errbuf
	)
{
	char *proxydn = NULL;
	Slapi_DN *requestor_sdn, *entry_sdn;
	char *errtext = NULL;
	int isroot;
	int rc;

	/*
	 * Theorically, we should check if the entry has "g"
	 * permission granted to the requestor. If granted,
	 * allows the effective rights on that entry and its
	 * attributes within the entry to be returned for
	 * ANY subject.
	 *
	 * "G" permission granting has not been implemented yet,
	 * the current release assumes that "g" permission be 
	 * granted to root and owner of any entry.
	 */

	/*
	 * The requestor may be either the bind dn or a proxy dn
	 */
	if ((proxyauth_get_dn( pb, &proxydn, &errtext ) == LDAP_SUCCESS) && ( proxydn != NULL ))
	{
		requestor_sdn = slapi_sdn_new_dn_passin ( proxydn );
	}
	else
	{
		requestor_sdn = &(pb->pb_op->o_sdn);
	}
	if ( slapi_sdn_get_dn (requestor_sdn) == NULL )
	{
		slapi_log_error (SLAPI_LOG_ACL, plugin_name,
				"_ger_g_permission_granted: anonymous has no g permission\n" );
		rc = LDAP_INSUFFICIENT_ACCESS;
		goto bailout;
	}
	isroot = slapi_dn_isroot ( slapi_sdn_get_dn (requestor_sdn) );
	if ( isroot )
	{
		/* Root has "g" permission on any entry */
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	entry_sdn = slapi_entry_get_sdn ( e );
	if ( entry_sdn == NULL || slapi_sdn_get_dn (entry_sdn) == NULL )
	{
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	if ( slapi_sdn_compare ( requestor_sdn, entry_sdn ) == 0 )
	{
		/* Owner has "g" permission on his own entry */
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	/* if the requestor and the subject user are identical, let's grant it */
	if ( strcasecmp ( slapi_sdn_get_ndn(requestor_sdn), subjectdn ) == 0)
	{
		/* Requestor should see his own permission rights on any entry */
		rc = LDAP_SUCCESS;
		goto bailout;
	}

	aclutil_str_append ( errbuf, "get-effective-rights: requestor has no g permission on the entry" );
	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
				"_ger_g_permission_granted: %s\n", *errbuf);
	rc = LDAP_INSUFFICIENT_ACCESS;

bailout:
	if ( proxydn )
	{
		/* The ownership of proxydn has passed to requestor_sdn */ 
		slapi_sdn_free ( &requestor_sdn );
	}
	return rc;
}
コード例 #17
0
ファイル: psearch.c プロジェクト: leto/389-ds
/*
 * Thread routine for sending search results to a client
 * which is persistently waiting for them.
 *
 * This routine will terminate when either (a) the ps_complete
 * flag is set, or (b) the associated operation is abandoned.
 * In any case, the thread won't notice until it wakes from
 * sleeping on the ps_list condition variable, so it needs
 * to be awakened.
 */
static void
ps_send_results( void *arg )
{
    PSearch *ps = (PSearch *)arg;
	PSEQNode *peq, *peqnext;
	struct slapi_filter *filter = 0;
	char *base = NULL;
	Slapi_DN *sdn = NULL;
	char *fstr = NULL;
	char **pbattrs = NULL;
	int conn_acq_flag = 0;
    
    g_incr_active_threadcnt();

    /* need to acquire a reference to this connection so that it will not
       be released or cleaned up out from under us */
    PR_Lock( ps->ps_pblock->pb_conn->c_mutex );
    conn_acq_flag = connection_acquire_nolock(ps->ps_pblock->pb_conn);    
    PR_Unlock( ps->ps_pblock->pb_conn->c_mutex );

	if (conn_acq_flag) {
		slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
						"conn=%" NSPRIu64 " op=%d Could not acquire the connection - psearch aborted\n",
						ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid);
	}

    PR_Lock( psearch_list->pl_cvarlock );

    while ( (conn_acq_flag == 0) && !ps->ps_complete ) {
	/* Check for an abandoned operation */
	if ( ps->ps_pblock->pb_op == NULL || slapi_op_abandoned( ps->ps_pblock ) ) {
		slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
						"conn=%" NSPRIu64 " op=%d The operation has been abandoned\n",
						ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid);
	    break;
	}
	if ( NULL == ps->ps_eq_head ) {
	    /* Nothing to do */
	    PR_WaitCondVar( psearch_list->pl_cvar, PR_INTERVAL_NO_TIMEOUT );
	} else {
	    /* dequeue the item */
	    int		attrsonly;
	    char	**attrs;
	    LDAPControl	**ectrls;
	    Slapi_Entry	*ec;
		Slapi_Filter	*f = NULL;
		
	    PR_Lock( ps->ps_lock );

		peq = ps->ps_eq_head;
		ps->ps_eq_head = peq->pe_next;
	    if ( NULL == ps->ps_eq_head ) {
			ps->ps_eq_tail = NULL;
	    }

	    PR_Unlock( ps->ps_lock );

	    /* Get all the information we need to send the result */
	    ec = peq->pe_entry;
	    slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRS, &attrs );
	    slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
	    if ( !ps->ps_send_entchg_controls || peq->pe_ctrls[0] == NULL ) {
		ectrls = NULL;
	    } else {
		ectrls = peq->pe_ctrls;
	    }

	    /*
	     * Send the result.  Since send_ldap_search_entry can block for
	     * up to 30 minutes, we relinquish all locks before calling it.
	     */
	    PR_Unlock(psearch_list->pl_cvarlock);

		/*
		 * The entry is in the right scope and matches the filter
		 * but we need to redo the filter test here to check access
		 * controls. See the comments at the slapi_filter_test()
		 * call in ps_service_persistent_searches().		 
		*/
		slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_FILTER, &f );			

		/* See if the entry meets the filter and ACL criteria */
		if ( slapi_vattr_filter_test( ps->ps_pblock, ec, f,
			    1 /* verify_access */ ) == 0 ) {
			int rc = 0;
	    	slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_RESULT_ENTRY, ec );
	    	rc = send_ldap_search_entry( ps->ps_pblock, ec,
										 ectrls, attrs, attrsonly );
			if (rc) {
				slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
								"conn=%" NSPRIu64 " op=%d Error %d sending entry %s with op status %d\n",
								ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid,
								rc, slapi_entry_get_dn_const(ec), ps->ps_pblock->pb_op->o_status);
			}
		}
	    
		PR_Lock(psearch_list->pl_cvarlock);

		/* Deallocate our wrapper for this entry */
		pe_ch_free( &peq );
	}
    }
    PR_Unlock( psearch_list->pl_cvarlock );
    ps_remove( ps );

    /* indicate the end of search */
    plugin_call_plugins( ps->ps_pblock , SLAPI_PLUGIN_POST_SEARCH_FN );

	/* free things from the pblock that were not free'd in do_search() */
	/* we strdup'd this in search.c - need to free */
	slapi_pblock_get( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, &base );
	slapi_pblock_set( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, NULL );
	slapi_ch_free_string(&base);

	/* Free SLAPI_SEARCH_* before deleting op since those are held by op */
	slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, &sdn );
	slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, NULL );
	slapi_sdn_free(&sdn);

    slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_STRFILTER, &fstr );
    slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_STRFILTER, NULL );
	slapi_ch_free_string(&fstr);

    slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRS, &pbattrs );
    slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_ATTRS, NULL );
	if ( pbattrs != NULL )
	{
		charray_free( pbattrs );
	}
	
	slapi_pblock_get(ps->ps_pblock, SLAPI_SEARCH_FILTER, &filter );
	slapi_pblock_set(ps->ps_pblock, SLAPI_SEARCH_FILTER, NULL );
	slapi_filter_free(filter, 1);

    /* Clean up the connection structure */
    PR_Lock( ps->ps_pblock->pb_conn->c_mutex );

	slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
					"conn=%" NSPRIu64 " op=%d Releasing the connection and operation\n",
					ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid);
    /* Delete this op from the connection's list */
    connection_remove_operation( ps->ps_pblock->pb_conn, ps->ps_pblock->pb_op );
    operation_free(&(ps->ps_pblock->pb_op),ps->ps_pblock->pb_conn);
    ps->ps_pblock->pb_op=NULL;

    /* Decrement the connection refcnt */
    if (conn_acq_flag == 0) { /* we acquired it, so release it */
	connection_release_nolock (ps->ps_pblock->pb_conn);
    }
    PR_Unlock( ps->ps_pblock->pb_conn->c_mutex );

    PR_DestroyLock ( ps->ps_lock );
    ps->ps_lock = NULL;

    slapi_ch_free((void **) &ps->ps_pblock );
	for ( peq = ps->ps_eq_head; peq; peq = peqnext) {
		peqnext = peq->pe_next;
		pe_ch_free( &peq );
	}
    slapi_ch_free((void **) &ps );
    g_decr_active_threadcnt();
}
コード例 #18
0
ファイル: retrocl_create.c プロジェクト: leto/389-ds
static int retrocl_create_be(const char *bedir)
{
    Slapi_PBlock *pb = NULL;
    Slapi_Entry *e;
    struct berval *vals[2];
    struct berval val;
    int rc;

    vals[0] = &val;
    vals[1] = NULL; 

    e = slapi_entry_alloc();
    /* RETROCL_LDBM_DN is no need to be normalized. */
    slapi_entry_set_dn(e,slapi_ch_strdup(RETROCL_LDBM_DN));

    /* Set the objectclass attribute */
    val.bv_val = "top";
    val.bv_len = 3;
    slapi_entry_add_values( e, "objectclass", vals );

    /* Set the objectclass attribute */
    val.bv_val = "extensibleObject";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "objectclass", vals );

    /* Set the objectclass attribute */
    val.bv_val = "nsBackendInstance";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "objectclass", vals );

    val.bv_val = "changelog";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "cn", vals );

    val.bv_val = RETROCL_BE_CACHESIZE;
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsslapd-cachesize", vals );

    val.bv_val = RETROCL_CHANGELOG_DN;
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsslapd-suffix", vals );

    val.bv_val = RETROCL_BE_CACHEMEMSIZE;
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsslapd-cachememsize", vals );

    val.bv_val = "off";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsslapd-readonly", vals );
    
    if (bedir) {
        val.bv_val = (char *)bedir;  /* cast const */
	val.bv_len = strlen(val.bv_val);
	slapi_entry_add_values( e, "nsslapd-directory", vals );
    }

    pb = slapi_pblock_new ();
    slapi_add_entry_internal_set_pb( pb, e, NULL /* controls */, 
				     g_plg_identity[PLUGIN_RETROCL], 
				     0 /* actions */ );
    slapi_add_internal_pb (pb);
    slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_RESULT, &rc );
    slapi_pblock_destroy(pb);
    
    if (rc == 0) {
        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
			 "created changelog database node\n");
    } else if (rc == LDAP_ALREADY_EXISTS) {
        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
			 "changelog database node already existed\n");
    } else {
        slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME, "Changelog LDBM backend could not be created (%d)\n", rc);
	return rc;
    }


    /* we need the changenumber indexed */
    e = slapi_entry_alloc();
    /* RETROCL_INDEX_DN is no need to be normalized. */
    slapi_entry_set_dn(e,slapi_ch_strdup(RETROCL_INDEX_DN));

    /* Set the objectclass attribute */
    val.bv_val = "top";
    val.bv_len = 3;
    slapi_entry_add_values( e, "objectclass", vals );

    /* Set the objectclass attribute */
    val.bv_val = "nsIndex";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "objectclass", vals );

    val.bv_val = "changenumber";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "cn", vals );

    val.bv_val = "false";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nssystemindex", vals );

    val.bv_val = "eq";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsindextype", vals );

    val.bv_val = "integerOrderingMatch";
    val.bv_len = strlen(val.bv_val);
    slapi_entry_add_values( e, "nsMatchingRule", vals );

    pb = slapi_pblock_new ();
    slapi_add_entry_internal_set_pb( pb, e, NULL /* controls */, 
				     g_plg_identity[PLUGIN_RETROCL], 
				     0 /* actions */ );
    slapi_add_internal_pb (pb);
    slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_RESULT, &rc );
    slapi_pblock_destroy(pb);
    
    if (rc == 0) {
        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
			 "created changenumber index node\n");
    } else if (rc == LDAP_ALREADY_EXISTS) {
        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
			 "changelog index node already existed\n");
    } else {
        slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME, "Changelog LDBM backend changenumber index could not be created (%d)\n", rc);
	return rc;
    }

    return rc;
}
コード例 #19
0
ファイル: psearch.c プロジェクト: leto/389-ds
/*
 * Check if there are any persistent searches.  If so,
 * the check to see if the chgtype is one of those the
 * client is interested in.  If so, then check to see if
 * the entry matches any of the filters the searches.
 * If so, then enqueue the entry on that persistent search's
 * ps_entryqueue and signal it to wake up and send the entry.
 *
 * Note that if eprev is NULL we assume that the entry's DN
 * was not changed by the op. that called this function.  If
 * chgnum is 0 it is unknown so we won't ever send it to a
 * client in the EntryChangeNotification control.
 */
void
ps_service_persistent_searches( Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype,
	ber_int_t chgnum )
{
	LDAPControl *ctrl = NULL;
	PSearch	*ps = NULL;
	PSEQNode *pe = NULL;
	int  matched = 0;
	const char *edn;

	if ( !PS_IS_INITIALIZED()) {
		return;
	}

	if ( NULL == e ) {
		/* For now, some backends such as the chaining backend do not provide a post-op entry */
		return;
	}

	PSL_LOCK_READ();
	edn = slapi_entry_get_dn_const(e);

	for ( ps = psearch_list ? psearch_list->pl_head : NULL; NULL != ps; ps = ps->ps_next ) {
		char *origbase = NULL;
		Slapi_DN *base = NULL;
		Slapi_Filter	*f;
		int		scope;

		/* Skip the node that doesn't meet the changetype,
		 * or is unable to use the change in ps_send_results()
		 */
		if (( ps->ps_changetypes & chgtype ) == 0 ||
				ps->ps_pblock->pb_op == NULL ||
				slapi_op_abandoned( ps->ps_pblock ) ) {
			continue;
		}

		slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
						"conn=%" NSPRIu64 " op=%d entry %s with chgtype %d "
						"matches the ps changetype %d\n",
						ps->ps_pblock->pb_conn->c_connid,
						ps->ps_pblock->pb_op->o_opid,
						edn, chgtype, ps->ps_changetypes);

		slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_FILTER, &f );
		slapi_pblock_get( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, &origbase );
		slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, &base );
		slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_SCOPE, &scope );
		if (NULL == base) {
			base = slapi_sdn_new_dn_byref(origbase);
			slapi_pblock_set(ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, base);
		}

		/*
		 * See if the entry meets the scope and filter criteria.
		 * We cannot do the acl check here as this thread
		 * would then potentially clash with the ps_send_results()
		 * thread on the aclpb in ps->ps_pblock.
		 * By avoiding the acl check in this thread, and leaving all the acl
		 * checking to the ps_send_results() thread we avoid
		 * the ps_pblock contention problem.
		 * The lesson here is "Do not give multiple threads arbitary access
		 * to the same pblock" this kind of muti-threaded access
		 * to the same pblock must be done carefully--there is currently no
		 * generic satisfactory way to do this.
		*/
		if ( slapi_sdn_scope_test( slapi_entry_get_sdn_const(e), base, scope ) &&
			 slapi_vattr_filter_test( ps->ps_pblock, e, f, 0 /* verify_access */ ) == 0 ) {
			PSEQNode *pOldtail;

			/* The scope and the filter match - enqueue it */

			matched++;
			pe = (PSEQNode *)slapi_ch_calloc( 1, sizeof( PSEQNode ));
			pe->pe_entry = slapi_entry_dup( e );
			if ( ps->ps_send_entchg_controls ) {
				/* create_entrychange_control() is more
				 * expensive than slapi_dup_control()
				 */
				if ( ctrl == NULL ) {
					int rc;
					rc = create_entrychange_control( chgtype, chgnum,
							eprev ? slapi_entry_get_dn_const(eprev) : NULL,
							&ctrl );
					if ( rc != LDAP_SUCCESS ) {
		   				LDAPDebug( LDAP_DEBUG_ANY, "ps_service_persistent_searches:"
						" unable to create EntryChangeNotification control for"
						" entry \"%s\" -- control won't be sent.\n",
						slapi_entry_get_dn_const(e), 0, 0 );
					}
				}
				if ( ctrl ) {
					pe->pe_ctrls[0] = slapi_dup_control( ctrl );
				}
			}

			/* Put it on the end of the list for this pers search */
			PR_Lock( ps->ps_lock );
			pOldtail = ps->ps_eq_tail;
			ps->ps_eq_tail = pe;
			if ( NULL == ps->ps_eq_head ) {
				ps->ps_eq_head = ps->ps_eq_tail;
			}
			else {
				pOldtail->pe_next = ps->ps_eq_tail;
			}
			PR_Unlock( ps->ps_lock );
		}
	}

   	PSL_UNLOCK_READ();

	/* Were there any matches? */
	if ( matched ) {
		ldap_control_free( ctrl );
		/* Turn 'em loose */
		ps_wakeup_all();
		LDAPDebug( LDAP_DEBUG_TRACE, "ps_service_persistent_searches: enqueued entry "
			"\"%s\" on %d persistent search lists\n", slapi_entry_get_dn_const(e), matched, 0 );
	} else {
		LDAPDebug( LDAP_DEBUG_TRACE, "ps_service_persistent_searches: entry "
			"\"%s\" not enqueued on any persistent search lists\n", slapi_entry_get_dn_const(e), 0, 0 );
	}

}
コード例 #20
0
ファイル: aclgroup.c プロジェクト: leto/389-ds
/*
 *
 * aclg_get_usersGroup
 *
 *	If we already have a the group info then we are done. If we
 *	don't, then allocate a new one and attach it.
 *
 *	Inputs:
 *		struct	acl_pblock		-- The acl private block.
 *		char *n_dn			- normalized client's DN
 *
 *	Returns:
 *		aclUserGroup			- The Group info block.
 *
 */
aclUserGroup *
aclg_get_usersGroup ( struct acl_pblock *aclpb , char *n_dn) 
{

	aclUserGroup		*u_group, *f_group;

	if ( !aclpb ) {
		slapi_log_error( SLAPI_LOG_ACL, plugin_name, "NULL acl pblock\n" );
		return NULL;
	}

	if ( aclpb->aclpb_groupinfo )
		return aclpb->aclpb_groupinfo;

	ACLG_LOCK_GROUPCACHE_WRITE();

	/* try it one more time. We might have one in the meantime */
	aclg_init_userGroup  (aclpb, n_dn , 1 /* got the lock */);
	if ( aclpb->aclpb_groupinfo ) {
		ACLG_ULOCK_GROUPCACHE_WRITE();
		return aclpb->aclpb_groupinfo;
	}

	/*
	 * It is possible at this point that we already have a group cache for the user
	 * but is is invalid. We can't use it anayway. So, we march along and allocate a new one.
	 * That's fine as the invalid one will be deallocated when done.
	 */

	slapi_log_error( SLAPI_LOG_ACL, plugin_name, "ALLOCATING GROUP FOR:%s\n", n_dn );
	u_group = ( aclUserGroup * ) slapi_ch_calloc ( 1, sizeof ( aclUserGroup ) );
	
	u_group->aclug_refcnt = 1;
	if ( (u_group->aclug_refcnt_mutex = PR_NewLock()) == NULL ) {
		slapi_ch_free((void **)&u_group);
		ACLG_ULOCK_GROUPCACHE_WRITE();
		return(NULL);
	}

	u_group->aclug_member_groups = (char **)
					slapi_ch_calloc ( 1, 
					    (ACLUG_INCR_GROUPS_LIST * sizeof (char *)));
	u_group->aclug_member_group_size = ACLUG_INCR_GROUPS_LIST;
	u_group->aclug_numof_member_group = 0;

	u_group->aclug_notmember_groups = (char **)
					slapi_ch_calloc ( 1,
					   (ACLUG_INCR_GROUPS_LIST * sizeof (char *)));
	u_group->aclug_notmember_group_size = ACLUG_INCR_GROUPS_LIST;
	u_group->aclug_numof_notmember_group = 0;

	u_group->aclug_ndn = slapi_ch_strdup ( n_dn ) ;	
	
	u_group->aclug_signature = aclUserGroups->aclg_signature;

	/* Do we have alreday the max number. If we have then delete the last one */
	if ( aclUserGroups->aclg_num_userGroups >= ACL_MAXCACHE_USERGROUPS - 5 ) {
		aclUserGroup		*d_group;
		
		/* We need to traverse thru  backwards and delete the one with a refcnt = 0 */
		d_group = aclUserGroups->aclg_last;
		while ( d_group ) {
			if ( !d_group->aclug_refcnt ) {
				__aclg__delete_userGroup ( d_group );
				break;
			} else {
				d_group = d_group->aclug_prev;
			}
		}

		/* If we didn't find any, which should be never, 
		** we have 5 more tries to do it.
		*/
	} 
	f_group = aclUserGroups->aclg_first;
	u_group->aclug_next = f_group;
	if ( f_group ) f_group->aclug_prev = u_group;
		
	aclUserGroups->aclg_first =  u_group;
	if ( aclUserGroups->aclg_last == NULL )
		aclUserGroups->aclg_last = u_group;

	aclUserGroups->aclg_num_userGroups++;

	/* Put it in the queue */
	ACLG_ULOCK_GROUPCACHE_WRITE();

	/* Now hang on to it */
	aclpb->aclpb_groupinfo = u_group;
	return u_group;
}
コード例 #21
0
ファイル: acleffectiverights.c プロジェクト: leto/389-ds
int
acl_get_effective_rights (
	Slapi_PBlock    *pb,
	Slapi_Entry	    *e,			/* target entry */
	char			**attrs,	/* Attribute of	the entry */
	struct berval   *val,		/* value of attr. NOT USED */
	int		    	access,		/* requested access rights */
	char			**errbuf
	)
{
	Slapi_PBlock *gerpb = NULL;
	void *aclcb = NULL;
	char *subjectndn = NULL;
	char *gerstr = NULL;
	size_t gerstrsize = 0;
	size_t gerstrcap = 0;
	int iscritical = 1;
	int rc = LDAP_SUCCESS;

	*errbuf = '\0';

	if (NULL == e)	/* create a template entry from SLAPI_SEARCH_GERATTRS */
	{
		rc = _ger_generate_template_entry ( pb );
		slapi_pblock_get ( pb, SLAPI_SEARCH_RESULT_ENTRY, &e );
		if ( rc != LDAP_SUCCESS || NULL == e )
		{
			goto bailout;
		}
	}

	/*
	 * Get the subject
	 */
	rc = _ger_parse_control (pb, &subjectndn, &iscritical, errbuf );
	if ( rc != LDAP_SUCCESS )
	{
		goto bailout;
	}

	/*
	 * The requestor should have g permission on the entry
	 * to get the effective rights.
	 */
	rc = _ger_g_permission_granted (pb, e, subjectndn, errbuf);
	if ( rc != LDAP_SUCCESS )
	{
		goto bailout;
	}

	/*
	 * Construct a new pb
	 */
	rc = _ger_new_gerpb ( pb, e, subjectndn, &gerpb, &aclcb, errbuf );
	if ( rc != LDAP_SUCCESS )
	{
		goto bailout;
	}

	/* Get entry level effective rights */
	_ger_get_entry_rights ( gerpb, e, subjectndn, &gerstr, &gerstrsize, &gerstrcap, errbuf );

	/*
	 * Attribute level effective rights may not be NULL
	 * even if entry level's is.
	 */
	_ger_get_attrs_rights ( gerpb, e, subjectndn, attrs, &gerstr, &gerstrsize, &gerstrcap, errbuf );

bailout:
	/*
	 * Now construct the response control
	 */
	_ger_set_response_control ( pb, iscritical, rc );

	if ( rc != LDAP_SUCCESS )
	{
		gerstr = slapi_ch_smprintf("entryLevelRights: %d\nattributeLevelRights: *:%d", rc, rc );
	}

	slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name,
		"###### Effective Rights on Entry (%s) for Subject (%s) ######\n",
		e?slapi_entry_get_ndn(e):"null", subjectndn?subjectndn:"null");
	slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name, "%s\n", gerstr);

	/* Restore pb */
	_ger_release_gerpb ( &gerpb, &aclcb, pb );

	/*
	 * General plugin uses SLAPI_RESULT_TEXT for error text. Here
	 * SLAPI_PB_RESULT_TEXT is exclusively shared with add, dse and schema.
	 * slapi_pblock_set() will free any previous data, and
	 * pblock_done() will free SLAPI_PB_RESULT_TEXT.
	 */
	slapi_pblock_set (pb, SLAPI_PB_RESULT_TEXT, gerstr);

	if ( !iscritical )
	{
		/*
		 * If return code is not LDAP_SUCCESS, the server would
		 * abort sending the data of the entry to the client.
		 */
		rc = LDAP_SUCCESS;
	}

	slapi_ch_free ( (void **) &subjectndn );
	slapi_ch_free ( (void **) &gerstr );
	return rc;
}
コード例 #22
0
ファイル: plugin.c プロジェクト: osstech-jp/ReOpenLDAP
static Slapi_PBlock *
plugin_pblock_new(
	int type,
	int argc,
	char *argv[] )
{
	Slapi_PBlock	*pPlugin = NULL;
	Slapi_PluginDesc *pPluginDesc = NULL;
	lt_dlhandle	hdLoadHandle;
	int		rc;
	char		**av2 = NULL, **ppPluginArgv;
	char		*path = argv[2];
	char		*initfunc = argv[3];

	pPlugin = slapi_pblock_new();
	if ( pPlugin == NULL ) {
		rc = LDAP_NO_MEMORY;
		goto done;
	}

	slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
	slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)&argc );

	av2 = ldap_charray_dup( argv );
	if ( av2 == NULL ) {
		rc = LDAP_NO_MEMORY;
		goto done;
	}

	if ( argc > 0 ) {
		ppPluginArgv = &av2[4];
	} else {
		ppPluginArgv = NULL;
	}

	slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv );
	slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 );

	rc = slapi_int_load_plugin( pPlugin, path, initfunc, 1, NULL, &hdLoadHandle );
	if ( rc != 0 ) {
		goto done;
	}

	if ( slapi_pblock_get( pPlugin, SLAPI_PLUGIN_DESCRIPTION, (void **)&pPluginDesc ) == 0 &&
	     pPluginDesc != NULL ) {
		slapi_log_error(SLAPI_LOG_TRACE, "plugin_pblock_new",
				"Registered plugin %s %s [%s] (%s)\n",
				pPluginDesc->spd_id,
				pPluginDesc->spd_version,
				pPluginDesc->spd_vendor,
				pPluginDesc->spd_description);
	}

done:
	if ( rc != 0 && pPlugin != NULL ) {
		slapi_pblock_destroy( pPlugin );
		pPlugin = NULL;
		if ( av2 != NULL ) {
			ldap_charray_free( av2 );
		}
	}

	return pPlugin;
}
コード例 #23
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;
}