Esempio n. 1
0
/*
 * This routine sets up a "context" for evaluation of access control
 * on a given entry for an anonymous user.
 * It just factors out the scope and targetfilter info into a list
 * of indices of the global anom profile list, that apply to this
 * entry, and stores them in the aclpb.
 * It's use relies on the way that access control is checked in the mailine search
 * code in the core server, namely: check filter, check entry, then check each
 * attribute.  So, we call this in acl_access_allowed() before calling
 * aclanom_match_profile()--therafter, aclanom_match_profile() uses the
 * context to evaluate access to the entry and attributes.
 * 
 * If there are no anom profiles, or the anom profiles get cancelled
 * due to complex anon acis, then that's OK, aclanom_match_profile()
 * returns -1 and the mainline acl code kicks in.
 *
 * The lifetime of this context info is the time it takes to check
 * access control for all parts of this entry (filter, entry, attributes).
 * So, if for an example an entry changes and a given anom profile entry
 * no longer applies, we will not notice until the next round of access
 * control checking on the entry--this is acceptable.
 * 
 * The gain on doing this factoring in the following type of search
 * was approx 6%:
 * anon bind, 20 threads, exact match, ~20 attributes returned, 
 * (searchrate & DirectoryMark).
 * 
*/
void
aclanom_get_suffix_info(Slapi_Entry *e,
							struct acl_pblock *aclpb ) {
	int i;
	char     *ndn = NULL;
	Slapi_DN    *e_sdn;
	const char    *aci_ndn;
	struct scoped_entry_anominfo *s_e_anominfo =
			&aclpb->aclpb_scoped_entry_anominfo;

	ANOM_LOCK_READ ();
		
	s_e_anominfo->anom_e_nummatched=0;

	ndn = slapi_entry_get_ndn ( e ) ;
	e_sdn= slapi_entry_get_sdn ( e ) ;
	for (i=acl_anom_profile->anom_numacls-1; i >= 0; i-- ) {
		aci_ndn = slapi_sdn_get_ndn (acl_anom_profile->anom_targetinfo[i].anom_target);
		if (!slapi_sdn_issuffix(e_sdn,acl_anom_profile->anom_targetinfo[i].anom_target)
				|| (!slapi_is_rootdse(ndn) && slapi_is_rootdse(aci_ndn)))
						continue;
		if ( acl_anom_profile->anom_targetinfo[i].anom_filter ) {
			if ( slapi_vattr_filter_test( aclpb->aclpb_pblock, e,
                               		acl_anom_profile->anom_targetinfo[i].anom_filter, 
					0 /*don't do acess chk*/)  != 0)
				continue;
		}
		s_e_anominfo->anom_e_targetInfo[s_e_anominfo->anom_e_nummatched]=i;
		s_e_anominfo->anom_e_nummatched++;
	}
	ANOM_UNLOCK_READ (); 
}
Esempio n. 2
0
/*
 * Invoked when the task instance is added by the client (step 5 of the comment)
 * Get the necessary attributes from the task entry, and spawns a thread to do
 * the task.
 */
static int
task_sampletask_add(Slapi_PBlock *pb, Slapi_Entry *e,
                    Slapi_Entry *eAfter, int *returncode, char *returntext,
                    void *arg)
{
    PRThread *thread = NULL;
    const char *cn;
    int rv = SLAPI_DSE_CALLBACK_OK;
    Slapi_PBlock *mypb = NULL;
    Slapi_Task *task = NULL;
    const char *myarg;

    *returncode = LDAP_SUCCESS;
    if ((cn = fetch_attr(e, "cn", NULL)) == NULL) {
        *returncode = LDAP_OBJECT_CLASS_VIOLATION;
        rv = SLAPI_DSE_CALLBACK_ERROR;
        goto out;
    }

    /* get arg(s) */
    if ((myarg = fetch_attr(e, "myarg", NULL)) == NULL) {
        *returncode = LDAP_OBJECT_CLASS_VIOLATION;
        rv = SLAPI_DSE_CALLBACK_ERROR;
        goto out;
    }

    /* allocate new task now */
    task = slapi_new_task(slapi_entry_get_ndn(e));
    if (task == NULL) {
        slapi_log_err(SLAPI_LOG_ERR, "sampletask", "unable to allocate new task!\n");
        *returncode = LDAP_OPERATIONS_ERROR;
        rv = SLAPI_DSE_CALLBACK_ERROR;
        goto out;
    }

    /* set a destructor that will clean up myarg for us when the task is complete */
    slapi_task_set_destructor_fn(task, task_sampletask_destructor);

    /* Stash our argument in the task for use by the task thread */
    slapi_task_set_data(task, slapi_ch_strdup(myarg));

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

out:
    return rv;
}
Esempio n. 3
0
static int
acl_default_access ( Slapi_PBlock *pb , Slapi_Entry *e, int access)
{

	int				isRoot, rootdse, accessCheckDisabled;
	int				 rc;

	slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot);
	if ( isRoot )  return LDAP_SUCCESS;	

	rc = slapi_pblock_get ( pb, SLAPI_PLUGIN_DB_NO_ACL, &accessCheckDisabled );
    if (  rc != -1 && accessCheckDisabled ) return LDAP_SUCCESS;

	rootdse = slapi_is_rootdse ( slapi_entry_get_ndn ( e ) );
    if (  rootdse && (access & (SLAPI_ACL_READ | SLAPI_ACL_SEARCH) ) )
		return LDAP_SUCCESS;

	return LDAP_INSUFFICIENT_ACCESS;
}
Esempio n. 4
0
/*
 * 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_err(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_err(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_err(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);
	}
    
    if (config_get_moddn_aci()) {
        /* The server enforces the new MODDN aci right.
         * So the status 'n' is set if this right is granted.
         * Opposed to the legacy mode where this flag is set if 
         * WRITE was granted on rdn attrbibute
         */
        if (acl_access_allowed(gerpb, e, NULL, NULL, SLAPI_ACL_MODDN) == LDAP_SUCCESS) {
            slapi_log_err(SLAPI_LOG_ACL, plugin_name,
                    "_ger_get_entry_rights - SLAPI_ACL_MODDN %s\n", slapi_entry_get_ndn(e));
            /* n - rename e */
            entryrights |= SLAPI_ACL_MODDN;
            _append_gerstr(gerstr, gerstrsize, gerstrcap, "n", NULL);
        }
    } else {
        /*
         * 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_err(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;
}
Esempio n. 5
0
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 = 0; /* critical may be missing or false http://tools.ietf.org/html/draft-ietf-ldapext-acl-model-08 */
	int rc = LDAP_SUCCESS;

	*errbuf = NULL;

	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_err(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_err(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;
}
Esempio n. 6
0
/*
  Given an entry, provide the account policy in effect for that entry.
  Returns non-0 if function fails.  If account policy comes back NULL, it's
  not an error; the entry is simply not covered by a policy.
*/
int
get_acctpolicy( Slapi_PBlock *pb, Slapi_Entry *target_entry, void *plugin_id,
                acctPolicy **policy )
{
    Slapi_DN *sdn = NULL;
    Slapi_Entry *policy_entry = NULL;
    Slapi_Attr *attr;
    Slapi_Value *sval = NULL;
    int ldrc;
    char *attr_name;
    char *policy_dn = NULL;
    acctPluginCfg *cfg;
    int rc = 0;

    if( policy == NULL ) {
        /* Bad parameter */
        return( -1 );
    }

    *policy = NULL;

    config_rd_lock();
    cfg = get_config();
    /* Return success and NULL policy */
    policy_dn = get_attr_string_val( target_entry, cfg->spec_attr_name );
    if( policy_dn == NULL ) {
        slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
                      "get_acctpolicy - \"%s\" is not governed by an account inactivity "
                      "policy subentry\n", slapi_entry_get_ndn( target_entry ) );
        if (cfg->inactivitylimit != ULONG_MAX) {
            goto dopolicy;
        }
        slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
                      "get_acctpolicy - \"%s\" is not governed by an account inactivity "
                      "global policy\n", slapi_entry_get_ndn( target_entry ) );
        config_unlock();
        return rc;
    }

    sdn = slapi_sdn_new_dn_byref( policy_dn );
    ldrc = slapi_search_internal_get_entry( sdn, NULL, &policy_entry,
                                            plugin_id );
    slapi_sdn_free( &sdn );

    /* There should be a policy but it can't be retrieved; fatal error */
    if( policy_entry == NULL ) {
        if( ldrc != LDAP_NO_SUCH_OBJECT ) {
            slapi_log_err(SLAPI_LOG_ERR, PLUGIN_NAME,
                          "get_acctpolicy - Error retrieving policy entry \"%s\": %d\n", policy_dn, ldrc );
        } else {
            slapi_log_err(SLAPI_LOG_PLUGIN, PLUGIN_NAME,
                          "get_acctpolicy - Policy entry \"%s\" is missing: %d\n", policy_dn, ldrc );
        }
        rc = -1;
        goto done;
    }

dopolicy:
    *policy = (acctPolicy *)slapi_ch_calloc( 1, sizeof( acctPolicy ) );

    if ( !policy_entry ) { /* global policy */
        (*policy)->inactivitylimit = cfg->inactivitylimit;
        goto done;
    }

    for( slapi_entry_first_attr( policy_entry, &attr ); attr != NULL;
            slapi_entry_next_attr( policy_entry, attr, &attr ) ) {
        slapi_attr_get_type(attr, &attr_name);
        if( !strcasecmp( attr_name, cfg->limit_attr_name ) ) {
            if( slapi_attr_first_value( attr, &sval ) == 0 ) {
                (*policy)->inactivitylimit = slapi_value_get_ulong( sval );
            }
        }
    }
done:
    config_unlock();
    slapi_ch_free_string( &policy_dn );
    slapi_entry_free( policy_entry );
    return( rc );
}
Esempio n. 7
0
int sidgen_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
                    Slapi_Entry *eAfter, int *returncode,
                    char *returntext, void *arg)
{
    int ret = SLAPI_DSE_CALLBACK_ERROR;
    const char *str;
    struct worker_ctx *worker_ctx = NULL;
    char *endptr;
    Slapi_Task *task = NULL;

    *returncode = LDAP_OPERATIONS_ERROR;
    returntext[0] = '\0';

    worker_ctx = (struct worker_ctx *) slapi_ch_calloc(1,
                                                     sizeof(struct worker_ctx));
    if (worker_ctx == NULL) {
        LOG_FATAL("slapi_ch_malloc failed!\n");
        *returncode = LDAP_OPERATIONS_ERROR;
        ret = SLAPI_DSE_CALLBACK_ERROR;
        goto done;
    }

    worker_ctx->plugin_id = global_sidgen_plugin_id;

    str = fetch_attr(e, "delay", NULL);
    if (str != NULL) {
        errno = 0;
        worker_ctx->delay = strtol(str, &endptr, 10);
        if (errno != 0 || worker_ctx->delay < 0) {
            LOG_FATAL("invalid delay [%s]!\n", str);
            *returncode = LDAP_CONSTRAINT_VIOLATION;
            ret = SLAPI_DSE_CALLBACK_ERROR;
            goto done;
        }
    }
    LOG("delay is [%li].\n", worker_ctx->delay);

    str = fetch_attr(e, "nsslapd-basedn", NULL);
    if (str == NULL) {
        LOG_FATAL("Missing nsslapd-basedn!\n");
        *returncode = LDAP_CONSTRAINT_VIOLATION;
        ret = SLAPI_DSE_CALLBACK_ERROR;
        goto done;
    }
    worker_ctx->base_dn = slapi_ch_strdup(str);
    if (worker_ctx->base_dn == NULL) {
        LOG_FATAL("Failed to copy base DN.\n");
        *returncode = LDAP_OPERATIONS_ERROR;
        ret = ENOMEM;
        goto done;
    }

    ret = get_dom_sid(worker_ctx->plugin_id, worker_ctx->base_dn,
                      &worker_ctx->dom_sid);
    if (ret != 0) {
        LOG_FATAL("Cannot find domain SID.\n");
        goto done;
    }

    ret = get_ranges(worker_ctx->plugin_id, worker_ctx->base_dn,
                     &worker_ctx->ranges);
    if (ret != 0) {
        LOG_FATAL("Cannot find ranges.\n");
        goto done;
    }

    task = slapi_new_task(slapi_entry_get_ndn(e));
    if (task == NULL) {
        LOG_FATAL("unable to allocate new task!\n");
        *returncode = LDAP_OPERATIONS_ERROR;
        ret = SLAPI_DSE_CALLBACK_ERROR;
        goto done;
    }

    slapi_task_set_destructor_fn(task, sidgen_task_destructor);
    slapi_task_set_data(task, worker_ctx);

    ret = pthread_create(&worker_ctx->tid, NULL, sidgen_task_thread, task);
    if (ret != 0) {
        LOG_FATAL("unable to create sidgen task thread!\n");
        *returncode = LDAP_OPERATIONS_ERROR;
        ret = SLAPI_DSE_CALLBACK_ERROR;
        slapi_task_finish(task, *returncode);
        goto done;
    }

    ret = SLAPI_DSE_CALLBACK_OK;
    *returncode = LDAP_SUCCESS;

done:
    if (ret != SLAPI_DSE_CALLBACK_OK) {
        slapi_ch_free((void **) &worker_ctx->base_dn);
        slapi_ch_free((void **) &worker_ctx);
    }
    return ret;
}
Esempio n. 8
0
/*
  Apply the pending changes in the e entry to our config struct.
  validate must have already been called
*/
static int 
pam_passthru_apply_config (Slapi_Entry* e)
{
    int rc = PAM_PASSTHRU_SUCCESS;
    char **excludes = NULL;
    char **includes = NULL;
    char *new_service = NULL;
    char *pam_ident_attr = NULL;
    char *map_method = NULL;
    char *dn = NULL;
    PRBool fallback;
    PRBool secure;
    Pam_PassthruConfig *entry = NULL;
    PRCList *list;
    Slapi_Attr *a = NULL;
    char *filter_str = NULL;
    int inserted = 0;

    pam_ident_attr = slapi_entry_attr_get_charptr(e, PAMPT_PAM_IDENT_ATTR);
    map_method = slapi_entry_attr_get_charptr(e, PAMPT_MAP_METHOD_ATTR);
    new_service = slapi_entry_attr_get_charptr(e, PAMPT_SERVICE_ATTR);
    excludes = slapi_entry_attr_get_charray(e, PAMPT_EXCLUDES_ATTR);
    includes = slapi_entry_attr_get_charray(e, PAMPT_INCLUDES_ATTR);
    fallback = slapi_entry_attr_get_bool(e, PAMPT_FALLBACK_ATTR);
    filter_str = slapi_entry_attr_get_charptr(e, PAMPT_FILTER_ATTR);
    /* Require SSL/TLS if the secure attr is not specified.  We
     * need to check if the attribute is present to make this
     * determiniation. */
    if (slapi_entry_attr_find(e, PAMPT_SECURE_ATTR, &a) == 0) {
        secure = slapi_entry_attr_get_bool(e, PAMPT_SECURE_ATTR);
    } else {
        secure = PR_TRUE;
    }

    /* Allocate a config struct. */
    entry = (Pam_PassthruConfig *)
        slapi_ch_calloc(1, sizeof(Pam_PassthruConfig));
    if (NULL == entry) {
        rc = PAM_PASSTHRU_FAILURE;
        goto bail;
    }

    /* use the RDN method to derive the PAM identity by default*/
    entry->pamptconfig_map_method1 = PAMPT_MAP_METHOD_RDN;
    entry->pamptconfig_map_method2 = PAMPT_MAP_METHOD_NONE;
    entry->pamptconfig_map_method3 = PAMPT_MAP_METHOD_NONE;

    /* Fill in the struct. */
    dn = slapi_entry_get_ndn(e);
    if (dn) {
        entry->dn = slapi_ch_strdup(dn);
    }

    entry->pamptconfig_fallback = fallback;
    entry->pamptconfig_secure = secure;

    if (!entry->pamptconfig_service ||
        (new_service && PL_strcmp(entry->pamptconfig_service, new_service))) {
        slapi_ch_free_string(&entry->pamptconfig_service);
        entry->pamptconfig_service = new_service;
        new_service = NULL; /* config now owns memory */
    }

    /* get the list of excluded suffixes */
    pam_ptconfig_free_suffixes(entry->pamptconfig_excludes);
    entry->pamptconfig_excludes = pam_ptconfig_add_suffixes(excludes);

    /* get the list of included suffixes */
    pam_ptconfig_free_suffixes(entry->pamptconfig_includes);
    entry->pamptconfig_includes = pam_ptconfig_add_suffixes(includes);

    if (!entry->pamptconfig_pam_ident_attr ||
        (pam_ident_attr && PL_strcmp(entry->pamptconfig_pam_ident_attr, pam_ident_attr))) {
        slapi_ch_free_string(&entry->pamptconfig_pam_ident_attr);
        entry->pamptconfig_pam_ident_attr = pam_ident_attr;
        pam_ident_attr = NULL; /* config now owns memory */
    }

    if (map_method) {
        parse_map_method(map_method,
        &entry->pamptconfig_map_method1,
        &entry->pamptconfig_map_method2,
        &entry->pamptconfig_map_method3,
        NULL);
    }

    if (filter_str) {
        entry->filter_str = filter_str;
        filter_str = NULL; /* config now owns memory */
        entry->slapi_filter = slapi_str2filter(entry->filter_str);
    }

    /* Add config to list.  We just store at the tail. */
    if (!PR_CLIST_IS_EMPTY(pam_passthru_global_config)) {
        list = PR_LIST_HEAD(pam_passthru_global_config);
        while (list != pam_passthru_global_config) {
            list = PR_NEXT_LINK(list);

            if (pam_passthru_global_config == list) {
                /* add to tail */
                PR_INSERT_BEFORE(&(entry->list), list);
                slapi_log_err(SLAPI_LOG_CONFIG, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                                "pam_passthru_apply_config - store [%s] at tail\n", entry->dn);
                inserted = 1;
                break;
            }
        }
    } else {
        /* first entry */
        PR_INSERT_LINK(&(entry->list), pam_passthru_global_config);
        slapi_log_err(SLAPI_LOG_CONFIG, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                        "pam_passthru_apply_config - store [%s] at head \n", entry->dn);
        inserted = 1;
    }

  bail:
    if(!inserted){
    	pam_passthru_free_config_entry(&entry);
    }
    slapi_ch_free_string(&new_service);
    slapi_ch_free_string(&map_method);
    slapi_ch_free_string(&pam_ident_attr);
    slapi_ch_free_string(&filter_str);
    slapi_ch_array_free(excludes);
    slapi_ch_array_free(includes);

    return rc;
}
Esempio n. 9
0
/*
 * Read and load configuration.  Validation will also
 * be performed unless skip_validate is set to non-0.
 * Returns PAM_PASSTHRU_SUCCESS if all is well.
 */
int
pam_passthru_load_config(int skip_validate)
{
    int status = PAM_PASSTHRU_SUCCESS;
    int result;
    int i;
    int alternate = 0;
    Slapi_PBlock *search_pb;
    Slapi_Entry **entries = NULL;

    slapi_log_err(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                     "=> pam_passthru_load_config\n");

    pam_passthru_write_lock();
    pam_passthru_delete_config();

    search_pb = slapi_pblock_new();

    /* Find all entries in the active config area. */
    slapi_search_internal_set_pb(search_pb, slapi_sdn_get_ndn(pam_passthru_get_config_area()),
                                 LDAP_SCOPE_SUBTREE, "objectclass=*",
                                 NULL, 0, NULL, NULL,
                                 pam_passthruauth_get_plugin_identity(), 0);
    slapi_search_internal_pb(search_pb);
    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);

    if (LDAP_SUCCESS != result) {
        status = PAM_PASSTHRU_FAILURE;
        goto cleanup;
    }

    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
                     &entries);
    if (NULL == entries || NULL == entries[0]) {
        status = PAM_PASSTHRU_FAILURE;
        goto cleanup;
    }

    /* Check if we are using an alternate config area.  We do this here
     * so we don't have to check each every time in the loop below. */
    if (slapi_sdn_compare(pam_passthru_get_config_area(),
            pam_passthruauth_get_plugin_sdn()) != 0) {
        alternate = 1;
    }

    /* Validate and apply config if valid.  If skip_validate is set, we skip
     * validation and just apply the config.  This should only be done if the
     * configuration has already been validated. */
    for (i = 0; (entries[i] != NULL); i++) {
        /* If this is the alternate config container, skip it since
         * we don't consider it to be an actual config entry. */
        if (alternate && (slapi_sdn_compare(pam_passthru_get_config_area(),
                slapi_entry_get_sdn(entries[i])) == 0)) {
            continue;
        }

        if (skip_validate || (PAM_PASSTHRU_SUCCESS == pam_passthru_validate_config(entries[i], NULL))) {
            if (PAM_PASSTHRU_FAILURE == pam_passthru_apply_config(entries[i])) {
                slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                                 "pam_passthru_load_config - Unable to apply config "
                                 "for entry \"%s\"\n", slapi_entry_get_ndn(entries[i]));
            }
        } else {
            slapi_log_err(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                             "pam_passthru_load_config - Skipping invalid config "
                             "entry \"%s\"\n", slapi_entry_get_ndn(entries[i]));
        }
    }

  cleanup:
    slapi_free_search_results_internal(search_pb);
    slapi_pblock_destroy(search_pb);
    pam_passthru_unlock();
    slapi_log_err(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
                    "<= pam_passthru_load_config\n");

    return status;
}
Esempio n. 10
0
File: urp.c Progetto: ohamada/389ds
/*
 * Return 0 for OK,
 *       -1 for Ignore or Error depending on SLAPI_RESULT_CODE,
 *       >0 for action code
 * Action Code Bit 0: Fetch existing entry.
 * Action Code Bit 1: Fetch parent entry.
 * The function is called as a be pre-op on consumers.
 */
int 
urp_add_operation( Slapi_PBlock *pb )
{
	Slapi_Entry	*existing_uniqueid_entry;
	Slapi_Entry	*existing_dn_entry;
	Slapi_Entry	*addentry;
	const char *adduniqueid;
	CSN *opcsn;
	const char *basedn;
	char sessionid[REPL_SESSION_ID_SIZE];
	int r;
	int op_result= 0;
	int rc= 0; /* OK */
	Slapi_DN *sdn = NULL;

	if ( slapi_op_abandoned(pb) )
	{
		return rc;
	}

	get_repl_session_id (pb, sessionid, &opcsn);
	slapi_pblock_get( pb, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, &existing_uniqueid_entry );
	if (existing_uniqueid_entry!=NULL)
	{
		/* 
		 * An entry with this uniqueid already exists.
		 * - It could be a replay of the same Add, or
		 * - It could be a UUID generation collision, or
		 */
		/* 
		 * This operation won't be replayed.  That is, this CSN won't update
		 * the max csn in RUV. The CSN is left uncommitted in RUV unless an
		 * error is set to op_result.  Just to get rid of this CSN from RUV,
		 * setting an error to op_result
		 */
		/* op_result = LDAP_SUCCESS; */
		slapi_log_error(slapi_log_urp, sessionid,
		          "urp_add (%s): an entry with this uniqueid already exists.\n",
		          slapi_entry_get_dn_const(existing_uniqueid_entry));
		op_result= LDAP_UNWILLING_TO_PERFORM;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
		rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
		PROFILE_POINT; /* Add Conflict; UniqueID Exists;  Ignore */
		goto bailout;
	}

	slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &addentry );
	slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &existing_dn_entry );
	if (existing_dn_entry==NULL) /* The target DN does not exist */
	{
		/* Check for parent entry... this could be an orphan. */
		Slapi_Entry *parententry;
		slapi_pblock_get( pb, SLAPI_ADD_PARENT_ENTRY, &parententry );
		rc = urp_add_resolve_parententry (pb, sessionid, addentry, parententry, opcsn);
		PROFILE_POINT; /* Add Entry */
		goto bailout;
	}

	/*
	 * Naming conflict: an entry with the target DN already exists.
	 * Compare the DistinguishedNameCSN of the existing entry
	 * and the OperationCSN. The smaller CSN wins. The loser changes
	 * its RDN to uniqueid+baserdn, and adds operational attribute
	 * ATTR_NSDS5_REPLCONFLIC.
	 */
	basedn = slapi_entry_get_ndn (addentry);
	adduniqueid = slapi_entry_get_uniqueid (addentry);
	r = csn_compare (entry_get_dncsn(existing_dn_entry), opcsn);
	if (r<0)
	{
		/* Entry to be added is a loser */
		char *newdn= get_dn_plus_uniqueid (sessionid, basedn, adduniqueid);
		if(newdn==NULL)
		{
			op_result= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
			rc = SLAPI_PLUGIN_NOOP; /* Abort this Operation */
			slapi_log_error(slapi_log_urp, sessionid,
			      "urp_add (%s): Add conflict; Unique ID (%s) already in RDN\n",
			      basedn, adduniqueid);
			PROFILE_POINT; /* Add Conflict; Entry Exists; Unique ID already in RDN - Abort this update. */
		}
		else
		{
			/* Add the nsds5ReplConflict attribute in the mods */
			Slapi_Attr *attr = NULL;
			Slapi_Value **vals = NULL;
			Slapi_RDN *rdn;
			char buf[BUFSIZ];

			PR_snprintf(buf, BUFSIZ, "%s %s", REASON_ANNOTATE_DN, basedn);
			if (slapi_entry_attr_find (addentry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0)
			{
				/* ATTR_NSDS5_REPLCONFLICT exists */
				slapi_log_error(SLAPI_LOG_FATAL, sessionid,
				          "urp_add: New entry has nsds5ReplConflict already\n");
				vals = attr_get_present_values (attr); /* this returns a pointer to the contents */
			}
			if ( vals == NULL || *vals == NULL )
			{
				/* Add new attribute */
				slapi_entry_add_string (addentry, ATTR_NSDS5_REPLCONFLICT, buf);
			}
			else
			{
				/*
				 * Replace old attribute. We don't worry about the index
				 * change here since the entry is yet to be added.
				 */
				slapi_value_set_string (*vals, buf);
			}
			/* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */
			slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
			slapi_sdn_free(&sdn);

			slapi_entry_set_normdn(addentry, newdn); /* dn: passin */

			sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(addentry));
			slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, sdn);

			rdn = slapi_rdn_new_sdn ( slapi_entry_get_sdn_const(addentry) );
			slapi_log_error (slapi_log_urp, sessionid,
			                 "urp_add: Naming conflict ADD. Add %s instead\n",
			                 slapi_rdn_get_rdn(rdn));
			slapi_rdn_free(&rdn);

			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
			PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Operation Entry */
		}
	}
	else if(r>0)
	{
		/* Existing entry is a loser */
		if (!urp_annotate_dn(sessionid, existing_dn_entry, opcsn, "ADD"))
		{
			op_result= LDAP_OPERATIONS_ERROR;
			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
			slapi_log_error(slapi_log_urp, sessionid,
			                "urp_add (%s): Entry to be added is a loser; "
			                "urp_annotate_dn failed.\n", basedn);
			rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
		}
		else
		{
			/* The backend add code should now search for the existing entry again. */
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
		}
		PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Existing Entry */
	}
	else /* r==0 */
	{
		/* The CSN of the Operation and the Entry DN are the same.
		 * This could only happen if:
		 * a) There are two replicas with the same ReplicaID.
		 * b) We've seen the Operation before.
		 * Let's go with (b) and ignore the little bastard.
		 */
		/* 
		 * This operation won't be replayed.  That is, this CSN won't update
		 * the max csn in RUV. The CSN is left uncommitted in RUV unless an
		 * error is set to op_result.  Just to get rid of this CSN from RUV,
		 * setting an error to op_result
		 */
		/* op_result = LDAP_SUCCESS; */
		slapi_log_error(slapi_log_urp, sessionid,
		"urp_add (%s): The CSN of the Operation and the Entry DN are the same.",
		slapi_entry_get_dn_const(existing_dn_entry));
		op_result= LDAP_UNWILLING_TO_PERFORM;
		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
		rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
		PROFILE_POINT; /* Add Conflict; Entry Exists; Same CSN */
	}

bailout:
	return rc;
}
Esempio n. 11
0
/*
 * 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;
}
Esempio n. 12
0
/*
 * aclanom_match_profile
 *	Look at the anonymous profile and see if we can use it or not.
 *
 *
 *	Inputs:
 *		Slapi_Pblock			- The Pblock
 *		Slapi_Entry *e			- The entry for which we are asking permission.
 *		char *attr			- Attribute name
 *		int  access			- access type
 *
 *	Return:
 *		LDAP_SUCCESS ( 0 )		- acess is allowed.
 *		LDAP_INSUFFICIENT_ACCESS (50 )  - access denied.
 *		-1			        - didn't match the targets
 *
 * Assumptions:
 * 	The caller of this module has to make sure that the client is 
 *	an anonymous client.
 */
int
aclanom_match_profile (Slapi_PBlock *pb, struct acl_pblock *aclpb, Slapi_Entry *e,
						char *attr, int access ) 
{

	struct	anom_profile	*a_profile;
	int						result, i, k;
	char					**destArray;
	int						tmatched = 0;
	int						loglevel;
	struct scoped_entry_anominfo *s_e_anominfo =
			&aclpb->aclpb_scoped_entry_anominfo;

	loglevel = slapi_is_loglevel_set(SLAPI_LOG_ACL) ? SLAPI_LOG_ACL : SLAPI_LOG_ACLSUMMARY;

	/* WE are only interested for READ/SEARCH  */
	if (  !(access & ( SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) )
		return -1;

	/* If we are here means, the client is doing a anonymous read/search */
	if ((a_profile = acl_anom_profile) == NULL ) {
		return -1;
	}		

	ANOM_LOCK_READ ();
	/* Check the signature first */
	if ( a_profile->anom_signature != acl_get_aclsignature () ) {
		/* Need to regenrate the signature.
	 	 * Need a WRITE lock to generate the anom profile  -
	 	 * which is obtained in acl__gen_anom_user_profile (). Since
	 	 * I don't have upgrade lock -- I have to do this way.
	 	 */
		ANOM_UNLOCK_READ ();
		aclanom_gen_anomProfile (DO_TAKE_ACLCACHE_READLOCK);
		aclanom_get_suffix_info(e, aclpb );
		ANOM_LOCK_READ ();
	}

	/* doing this early saves use a malloc/free/normalize cost */
	if ( !a_profile->anom_numacls ) {
		ANOM_UNLOCK_READ ();
		return -1;
	}

	result = LDAP_INSUFFICIENT_ACCESS;

	for ( k=0; k<s_e_anominfo->anom_e_nummatched; k++ ) {
		short	matched = 0;
		short	j = 0;	
	
		i = s_e_anominfo->anom_e_targetInfo[k];
	
		/* Check for right */
		if ( !(a_profile->anom_targetinfo[i].anom_access & access) )
			continue;
		
		/*
		 * XXX rbyrne Don't really understand the role of this
		 * but not causing any obvious bugs...get back to it.
		*/		
		tmatched++;
		
		if ( attr == NULL ) {
			result = LDAP_SUCCESS;
			break;
		}

		destArray = a_profile->anom_targetinfo[i].anom_targetAttrs;
		while ( destArray[j] ) {
			if ( strcasecmp ( destArray[j], "*") == 0 ||
				slapi_attr_type_cmp ( attr, destArray[j], 1 ) == 0 ) {
				matched = 1;
				break;
			}
			j++;
		}
		
		if ( a_profile->anom_targetinfo[i].anom_type  & ACI_TARGET_ATTR_NOT )
			result = matched ? LDAP_INSUFFICIENT_ACCESS : LDAP_SUCCESS;
		else 
			result = matched ? LDAP_SUCCESS : LDAP_INSUFFICIENT_ACCESS;
	
		if ( result == LDAP_SUCCESS )
			break;
	} /* for */

	if ( slapi_is_loglevel_set(loglevel) ) {
		char					*ndn = NULL;
		Slapi_Operation			*op = NULL;
		PRUint64 o_connid = 0xffffffffffffffff; /* no op */
		int o_opid = -1; /* no op */
 
		ndn = slapi_entry_get_ndn ( e ) ;
		slapi_pblock_get(pb, SLAPI_OPERATION, &op);
		if (op) {
			o_connid = op->o_connid;
			o_opid = op->o_opid;
		}

		if ( result == LDAP_SUCCESS) {
			const char				*aci_ndn;
			aci_ndn = slapi_sdn_get_ndn (acl_anom_profile->anom_targetinfo[i].anom_target);
			if (access & SLAPI_ACL_MODDN) {
				slapi_log_err(loglevel, plugin_name, 
					"aclanom_match_profile - conn=%" NSPRIu64 " op=%d: Allow access on entry(%s).attr(%s) (from %s) to anonymous: acidn=\"%s\"\n",
					o_connid, o_opid,
					ndn,
					attr ? attr:"NULL",
					aclpb->aclpb_moddn_source_sdn ? slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn) : "NULL",
					aci_ndn);
				
			} else {
				slapi_log_err(loglevel, plugin_name, 
					"aclanom_match_profile - conn=%" NSPRIu64 " op=%d: Allow access on entry(%s).attr(%s) to anonymous: acidn=\"%s\"\n",
					o_connid, o_opid,
					ndn,
					attr ? attr:"NULL",
					aci_ndn);
			}
		} else {
			if (access & SLAPI_ACL_MODDN) {
				slapi_log_err(loglevel, plugin_name,
					"aclanom_match_profile - conn=%" NSPRIu64 " op=%d: Deny access on entry(%s).attr(%s) (from %s) to anonymous\n",
					o_connid, o_opid,
					ndn, attr ? attr:"NULL" ,
					aclpb->aclpb_moddn_source_sdn ? slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn) : "NULL");
			} else {
				slapi_log_err(loglevel, plugin_name,
					"aclanom_match_profile - conn=%" NSPRIu64 " op=%d: Deny access on entry(%s).attr(%s) to anonymous\n",
					o_connid, o_opid,
					ndn, attr ? attr:"NULL" );
			}
		}
	}

	ANOM_UNLOCK_READ ();
	if ( tmatched == 0) 
		return -1;
	else 
		return result;
}