Beispiel #1
0
/*
 *	Attempt to locate the index number for one of the known attribute names
 *	that are stored in plists.  If we can't match it, just return 0.
 */
int
ACL_Attr2Index(const char *attrname)
{
    int index = 0;

    if ( ACLAttr2IndexPList ) {
        PListFindValue(ACLAttr2IndexPList, attrname, (void **)&index, NULL);
        if (index < 0) index = 0;
    }
    return index;
}
//
// ACL_GetAttribute - find and call one or more matching attribute getter functions
//
NSAPI_PUBLIC int
ACL_GetAttribute(NSErr_t *errp, const char *attr, void **val,
		     		  PList_t subject, PList_t resource, 
				  PList_t auth_info, PList_t global_auth) 
{ 
    int rv; 
    void *attrval;
    ACLAttrGetterFn_t func;
    ACLAttrGetterList_t getters;
    ACLAttrGetter_t *getter;
    ACLMethod_t method;
    char *dbname;
    ACLDbType_t dbtype;

    /* If subject PList is NULL, we will fail anyway */
    if (!subject)
        return LAS_EVAL_FAIL;

    /* Is the attribute already present in the subject property list? */
    rv = PListFindValue(subject, attr, &attrval, NULL);
    if (rv >= 0) {
        /* Yes, take it from there */
	*val = attrval;
	return LAS_EVAL_TRUE;
    }

    /* Get the authentication method and database type */
    // XXX umm... for ACLs that do not depend on user databases and authentication
    // methods (like cipher, dns, ip, tod!), we do not need method and database type.
    // so there's no reason to fail if we don't find anything here.
    // I think setting method to ACL_METHOD_ANY and dbtype to ACL_DBTYPE_ANY would
    // do the job in attr_getter_is_matching - this way, we would find only attr
    // getters that do not care about method and dbtype.

    if (ACL_AuthInfoGetMethod(errp, auth_info, &method) < 0) {
	nserrGenerate(errp, ACLERRFAIL, ACLERR4300, ACL_Program, 2,
            XP_GetAdminStr(DBT_GetAttributeCouldntDetermineMethod), attr);
        return LAS_EVAL_FAIL;
    }

    // dbtype is cached by our friendly ACLEvalAce caller (it's constant for the ACE)
    // XXX what if we don't get called by ACLEvalAce?
    if (PListGetValue(resource, ACL_ATTR_DBTYPE_INDEX, &dbtype, NULL) < 0) {
        dbtype = ACL_DBTYPE_INVALID;
    }

    /* Get the list of attribute getters */
    if ((ACL_AttrGetterFind(errp, attr, &getters) < 0) || (getters == 0)) {
	nserrGenerate(errp, ACLERRFAIL, ACLERR4310, ACL_Program, 2,
                      XP_GetAdminStr(DBT_GetAttributeCouldntLocateGetter), attr);
        return LAS_EVAL_DECLINE;
    }

    // Iterate over each getter and see if it should be called
    // Call each matching getter until a getter which doesn't decline is
    // found.
    char * method_name = NULL;
    char * dbtype_name = NULL;

    for (getter = ACL_AttrGetterFirst(&getters); getter != 0; getter = ACL_AttrGetterNext(&getters, getter)) {

        /* Require matching method and database type */

        if (!attr_getter_is_matching(errp, getter, method, dbtype))
            continue;

        if (ereport_can_log(LOG_VERBOSE)) {
            method_name = acl_get_name(ACLMethodHash, method);
            dbtype_name = acl_get_name(ACLDbTypeHash, dbtype);
            ereport(LOG_VERBOSE, "acl: calling getter for (attr=%s; "
                    "method=%s, dbtype=%s)", attr, method_name, dbtype_name);
        }

        /* Call the getter function */
        func = getter->fn;
        rv = (*func)(errp, subject, resource, auth_info, global_auth, getter->arg);

        if (method_name) {
            ereport(LOG_VERBOSE, "acl: getter for (attr=%s; "
                    "method=%s, dbtype=%s) returns %d", 
                    attr, method_name, dbtype_name, rv);
            FREE(method_name);
            FREE(dbtype_name);
        }

        // if the getter declined, let's try to find another one
        if (rv == LAS_EVAL_DECLINE)
            continue;

        /* Did the getter succeed? */
        if (rv == LAS_EVAL_TRUE) {
            /*
             * Yes, it should leave the attribute on the subject
             * property list.
             */
            if (PListFindValue(subject, attr, (void **)&attrval, NULL) < 0) {
                nserrGenerate(errp, ACLERRFAIL, ACLERR4320, ACL_Program, 2,
                              XP_GetAdminStr(DBT_GetAttributeDidntSetAttr), attr);
                return LAS_EVAL_FAIL;
            }

            /* Got it */
            *val = attrval;
            return LAS_EVAL_TRUE;
        } else {
            /* No, did it fail to get the attribute */
            if (rv == LAS_EVAL_FAIL || rv == LAS_EVAL_INVALID) {
                nserrGenerate(errp, ACLERRFAIL, ACLERR4330, ACL_Program, 2,
                              XP_GetAdminStr(DBT_GetAttributeDidntGetAttr), attr);
            }
            return rv;
        }
    }

    // If we fall out of the loop, all the getters declined

    if (ereport_can_log(LOG_VERBOSE)) {
        method_name = acl_get_name(ACLMethodHash, method);
        dbtype_name = acl_get_name(ACLDbTypeHash, dbtype);
        ereport(LOG_VERBOSE, "acl: unable to obtain an attribute getter for "
                "[%s] with method [%s] (%d), dbtype [%s] (%d)", 
                attr, method_name, method, dbtype_name, dbtype);
        FREE(method_name);
        FREE(dbtype_name);
    }

    nserrGenerate(errp, ACLERRFAIL, ACLERR4340, ACL_Program, 2,
		  XP_GetAdminStr(DBT_GetAttributeAllGettersDeclined), attr);
    return LAS_EVAL_DECLINE;
}