Beispiel #1
0
NSAPI_PUBLIC ACLListHandle_t *
ACL_ParseString( NSErr_t *errp, char *buffer )
{
ACLListHandle_t 	*handle = NULL;
int			eid = 0;
int			rv = 0;
const char			*errmsg;

    ACL_InitAttr2Index();

    if ( acl_parse_crit == NULL )
        acl_parse_crit = crit_init();

    crit_enter( acl_parse_crit );

    if ( acl_InitScanner( errp, NULL, buffer ) < 0 ) {
        rv = ACLERRNOMEM;
        eid = ACLERR1920;
        nserrGenerate(errp, rv, eid, ACL_Program, 0);
    } else {
    
        handle = ACL_ListNew(errp);
        if ( handle == NULL ) {
            rv = ACLERRNOMEM;
            eid = ACLERR1920;
            nserrGenerate(errp, rv, eid, ACL_Program, 0);
        } else if ( acl_PushListHandle( handle ) < 0 ) {
            rv = ACLERRNOMEM;
            eid = ACLERR1920;
            nserrGenerate(errp, rv, eid, ACL_Program, 0);
        } else if ( acl_Parse() ) {
            rv = ACLERRPARSE;
            eid = ACLERR1780;
        }
    
        if ( acl_EndScanner() < 0 ) {
            rv = ACLERROPEN;
            eid = ACLERR1500;
            errmsg = system_errmsg();
            nserrGenerate(errp, rv, eid, ACL_Program, 2, "buffer", errmsg);
        }

    }

    if ( rv || eid ) {
        ACL_ListDestroy(errp, handle);
        handle = NULL;
    }

    crit_exit( acl_parse_crit );
    return(handle);

}
NSAPI_PUBLIC int
ACL_ListPostParseForAuth(NSErr_t *errp, ACLListHandle_t *acl_list ) 
{
    ACLHandle_t *acl;
    ACLWrapper_t *wrap;
    ACLExprHandle_t *expr;
    char *method;
    char *database;
    int rv;
    ACLDbType_t *dbtype;
    ACLMethod_t *methodtype;

    if ( acl_list == NULL )
        return(0);

    // for all ACLs
    for ( wrap = acl_list->acl_list_head; wrap; wrap = wrap->wrap_next ) {

        acl = wrap->acl;
        if ( acl == NULL )
            continue;

        // for all expressions with the ACL
        for ( expr = acl->expr_list_head; expr; expr = expr->expr_next ) {

            if ( expr->expr_type != ACL_EXPR_TYPE_AUTH || expr->expr_auth == NULL) 
                continue;

            // get method attribute - this is a name now
            rv = PListGetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, (void **) &method, NULL);
            if ( rv >= 0 ) {
		methodtype = (ACLMethod_t *)PERM_MALLOC(sizeof(ACLMethod_t));
		rv = ACL_MethodFind(errp, method, methodtype);
		if (rv < 0) {
		    nserrGenerate(errp, ACLERRUNDEF, ACLERR3800, ACL_Program,
				  3, acl->tag, "method", method);
		    PERM_FREE(methodtype);
		    return(ACLERRUNDEF);
		}

                // replace it with a method type
	        rv = PListSetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, methodtype, NULL);
		if ( rv < 0 ) {
		    nserrGenerate(errp, ACLERRNOMEM, ACLERR3810, ACL_Program, 0);
		    return(ACLERRNOMEM);
		}
		PERM_FREE(method);
	    }
        }
    }
    return(0);
}
/*    LASIpTreeAlloc
 *    Malloc a node and set the actions to LAS_EVAL_FALSE
 */
static LASIpTree_t *
LASIpTreeAllocNode(NSErr_t *errp)
{
    LASIpTree_t    *newnode;

    newnode = (LASIpTree_t *)PERM_MALLOC(sizeof(LASIpTree_t));
    if (newnode == NULL) {
	nserrGenerate(errp, ACLERRNOMEM, ACLERR5000, ACL_Program, 1, XP_GetAdminStr(DBT_lasiptreeallocNoMemoryN_));
        return NULL;
    }
    newnode->action[0] = (LASIpTree_t *)LAS_EVAL_FALSE;
    newnode->action[1] = (LASIpTree_t *)LAS_EVAL_FALSE;
    return newnode;
}
/* 
 * traverseTreeAndCompareIPs
 * This function compares bit by bit of IP address with the tree nodes
 * Input
 *   NSErr_t *errp
 *   PRNetAddr * ip_addr - IP address of the client
 *   LASIpContext *context
 *   char * attr_pattern - ip address/pattern passed into LASIpEval
 *   int ipVersion - ipVersion of clients IP Address
 *   bool comparator_is_equal - true if comparator is CMP_OP_EQ
 * Returns 
 * LAS_EVAL_TRUE or LAS_EVAL_FALSE, or  LAS_* error codes in case of error.
 */
int traverseTreeAndCompareIPs(NSErr_t *errp, PRNetAddr *ip_addr, 
                              LASIpContext *context, char *attr_pattern,
                              int ipVersion, bool comparator_is_equal)
{
    // special case ip=*
    if (context->ipVersion == (PR_AF_INET6+PR_AF_INET)) {
        if (comparator_is_equal) {
            ereport(LOG_VERBOSE, "acl ip: match on ip = (%s)",
                    attr_pattern);
            return(LAS_EVAL_TRUE);
        } else {
            ereport(LOG_VERBOSE, "acl ip: no match on ip != (%s)",
                    attr_pattern);
            return(LAS_EVAL_FALSE);
        }
    }
     
    LASIpTree_t *node    = context->treetop;

    if (context->ipVersion != ipVersion || node == NULL) {
        ereport(LOG_VERBOSE,
                "ERROR IP Address returned by Attribute Getter for ACL_ATTR_IP did not match with IP Address Version set in ACL file.");
        if (comparator_is_equal) {
            return(LAS_EVAL_FALSE);
        } else {
            return(LAS_EVAL_TRUE);
        }
    }
    int max_bits=32;
    if (ipVersion == PR_AF_INET6)
        max_bits=128;
    else if (ipVersion != PR_AF_INET)
       return LAS_EVAL_INVALID;

    for (int bit=(max_bits-1); bit >=0; bit--) {
        int value = getBit(*ip_addr,bit,max_bits);
        if (LAS_IP_IS_CONSTANT(node->action[value])) {
            /* Reached a result, so return it */
            int r = (int)(size_t) node->action[value];
            if (comparator_is_equal) {
                ereport(LOG_VERBOSE, "acl ip: %s on ip = (%s)",
                        (r == LAS_EVAL_TRUE) ? "match" : "no match",
                        attr_pattern);
                return(r);
            }
            else {
                ereport(LOG_VERBOSE, "acl ip: %s on ip != (%s)",
                        (r == LAS_EVAL_TRUE) ? "no match" : "match",
                        attr_pattern);
                return((r == LAS_EVAL_TRUE) ? 
                    LAS_EVAL_FALSE : LAS_EVAL_TRUE);
            }
        }
        else {
            /* Move on to the next bit */
            node = node->action[value];
        }
    }

    /* Cannot reach here.  Even a 32 bit mismatch has a conclusion in 
     * the pattern tree.
     */
    char ip_str[124];
    memset(ip_str,0,124);
    PR_NetAddrToString(ip_addr,ip_str,124);
    nserrGenerate(errp, ACLERRINTERNAL, ACLERR5240, ACL_Program, 2, XP_GetAdminStr(DBT_lasipevalReach32BitsWithoutConcl_), max_bits, ip_str);
    return LAS_EVAL_INVALID;
}
/*
 *    LASIpEval
 *    INPUT
 *    attr_name      The string "ip" - in lower case.
 *    comparator     CMP_OP_EQ or CMP_OP_NE only
 *    attr_pattern   A comma-separated list of IP addresses and netmasks
 *                   in dotted-decimal form.  Netmasks are optionally
 *                   prepended to the IP address using a plus sign.  E.g.
 *                   255.255.255.0+123.45.67.89.  Any byte in the IP address
 *                   (but not the netmask) can be wildcarded using "*"
 *    *cachable      Always set to ACL_INDEF_CACHABLE
 *    subject        Subject property list
 *    resource       Resource property list
 *    auth_info      The authentication info if any
 *    RETURNS
 *    ret code       The usual LAS return codes.
 */
int LASIpEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
          char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie,
          PList_t subject, PList_t resource, PList_t auth_info,
          PList_t global_auth)
{
    void               *pip;
    int                retcode;
    LASIpContext_t     *context;
    int		       rv;

#ifndef UTEST
    *cachable = ACL_INDEF_CACHABLE;
#endif

    if (strcmp(attr_name, "ip") != 0) {
	nserrGenerate(errp, ACLERRINVAL, ACLERR5200, ACL_Program, 2, XP_GetAdminStr(DBT_lasIpBuildReceivedRequestForAttr_), attr_name);
        return LAS_EVAL_INVALID;
    }

    if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
	nserrGenerate(errp, ACLERRINVAL, ACLERR5210, ACL_Program, 2, XP_GetAdminStr(DBT_lasipevalIllegalComparatorDN_), comparator_string(comparator));
        return LAS_EVAL_INVALID;
    }

    /* GET THE IP ADDR FROM THE SESSION CONTEXT AND STORE IT IN THE
     * VARIABLE ip.
     */
#ifndef    UTEST
    rv = ACL_GetAttribute(errp, ACL_ATTR_IP, &pip,
			  subject, resource, auth_info, global_auth);

    PRNetAddr *ip_addr = (PRNetAddr *)pip;
    if (rv != LAS_EVAL_TRUE) {
        if (subject || resource) {
            /* Don't ereport if called from ACL_CachableAclList */
	    char rv_str[16];
	    sprintf(rv_str, "%d", rv);
	    nserrGenerate(errp, ACLERRINVAL, ACLERR5220, ACL_Program, 2, XP_GetAdminStr(DBT_lasipevalUnableToGetSessionAddre_), rv_str);
        }
        ereport(LOG_VERBOSE,
                "ERROR Attribute Getter for ACL_ATTR_IP returned error %d.",
                rv);
	return LAS_EVAL_FAIL;
    }

#else
     PRNetAddr *ip_addr = LASIpGetIpv6();
    if (ip_addr == NULL) {
        ereport(LOG_VERBOSE,
                "ERROR IP Address returned from LASIpGetIpv6() is NULL.");
        return LAS_EVAL_FAIL;
    }
#endif
    int ipVersion = PR_AF_INET;
    if (ip_addr->ipv6.family == PR_AF_INET6) {
         ipVersion = PR_AF_INET6;
    } else if (ip_addr->inet.family != PR_AF_INET) {
         PR_ASSERT(0);
    }

    /* If this is the first time through, build the pattern tree first.
     */
    if (*LAS_cookie == NULL) {
        if (strcspn(attr_pattern, "0123456789.*ABCDEF:abcdef,+ \t")) {
            nserrGenerate(errp,ACLERRINVAL,ACLERR5120,ACL_Program,2,
                 XP_GetAdminStr(DBT_lasIpIncorrentIPPattern),attr_pattern);
            return LAS_EVAL_INVALID;
        }
        ACL_CritEnter();
        context = (LASIpContext *) *LAS_cookie;
        if (*LAS_cookie == NULL) {    /* must check again */
            *LAS_cookie = context = (LASIpContext_t *)PERM_MALLOC(sizeof(LASIpContext_t));
            if (context == NULL) {
		nserrGenerate(errp, ACLERRNOMEM, ACLERR5230, ACL_Program, 1, XP_GetAdminStr(DBT_lasipevalUnableToAllocateContext_));
                ACL_CritExit();
                return LAS_EVAL_FAIL;
            }
            context->treetop = NULL;
            retcode = LASIpBuild(errp, attr_pattern, &context->treetop, ipVersion);
            if ((retcode == PR_AF_INET6) ||
                (retcode == PR_AF_INET) ||
                (retcode == (PR_AF_INET6+PR_AF_INET)))
                 context->ipVersion = retcode;
            else {
                ACL_CritExit();
                return (retcode);
	    }
        }
	ACL_CritExit();
    } else
        context = (LASIpContext *) *LAS_cookie;

    return traverseTreeAndCompareIPs(errp, ip_addr, context, attr_pattern, 
                                     ipVersion, (comparator == CMP_OP_EQ)?1:0);
}
/*    LASIpAddPattern
 *    Takes a netmask and IP address and a pointer to an existing IP
 *    tree and adds nodes as appropriate to recognize the new pattern.
 *    INPUT
 *    netmask        netmask in PRNetAddr
 *    pattern        IP address in PRNetAddr
 *    *treetop    An existing IP tree or 0 if a new tree
 *    ipVersion   int PR_AF_INET or PR_AF_INET6
 *    RETURNS
 *    ret code    NULL on success, ACL_RES_ERROR on failure
 *    **treetop    If this is a new tree, the head of the tree.
 */
static int
LASIpAddPattern(NSErr_t *errp, PRNetAddr netmask, PRNetAddr pattern, LASIpTree_t **treetop, int ipVersion)
{
    int        stopbit;    /* Don't care after this point    */
    int        curbit;        /* current bit we're working on    */
    int        curval;        /* value of pattern[curbit]    */
    LASIpTree_t    *curptr;    /* pointer to the current node    */
    LASIpTree_t    *newptr;

    int max_bit = 32;
    if (ipVersion == PR_AF_INET6)
        max_bit = 128;
    else if (ipVersion != PR_AF_INET)
       return LAS_EVAL_INVALID;

    /* stop at the first 1 in the netmask from low to high         */
    for (stopbit=0;  stopbit<max_bit; stopbit++) {
        if (getBit(netmask,stopbit,max_bit) != 0)
            break;
    }

    /* Special case if there's no tree.  Allocate the first node    */
    if (*treetop == (LASIpTree_t *)NULL) {    /* No tree at all */
        curptr = LASIpTreeAllocNode(errp);
        if (curptr == NULL) {
	    nserrGenerate(errp, ACLERRFAIL, ACLERR5100, ACL_Program, 1, XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_));
            return ACL_RES_ERROR;
        }
        *treetop = curptr;
    } else
	curptr = *treetop;

    /* Special case if the netmask is 0.
     */
    if (stopbit > (max_bit -1)) {
        curptr->action[0] = (LASIpTree_t *)LAS_EVAL_TRUE;
        curptr->action[1] = (LASIpTree_t *)LAS_EVAL_TRUE;
        return 0;
    }


    /* follow the tree down the pattern path bit by bit until the
     * end of the tree is reached (i.e. a constant).
     */
    for (curbit=max_bit-1,curptr=*treetop; curbit >= 0; curbit--) {

        /* Is the current bit ON?  If so set curval to 1 else 0    */
        curval = getBit(pattern, curbit, max_bit);

        /* Are we done, if so remove the rest of the tree     */
        if (curbit == stopbit) {
            LASIpTreeDealloc(curptr->action[curval]);
            curptr->action[curval] = 
                    (LASIpTree_t *)LAS_EVAL_TRUE;

            /* This is the normal exit point.  Most other 
             * exits must be due to errors.
             */
            return 0;
        }

        /* Oops reached the end - must allocate        */
        if (LAS_IP_IS_CONSTANT(curptr->action[curval])) {
            newptr = LASIpTreeAllocNode(errp);
            if (newptr == NULL) {
                LASIpTreeDealloc(*treetop);
	        nserrGenerate(errp, ACLERRFAIL, ACLERR5110, ACL_Program, 1, XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_1));
                return ACL_RES_ERROR;
            }
            curptr->action[curval] = newptr;
        }

        /* Keep going down the tree                */
        curptr = curptr->action[curval];
    }

    return ACL_RES_ERROR;
}
/*
 *  LASIsLockOwnerEval
 *  INPUT
 *    attr_name     The string "is-lock-owner" - in lower case.
 *    comparator    CMP_OP_EQ or CMP_OP_NE only
 *    attr_pattern  "on", "off", "yes", "no", "true", "false", "1", "0"
 *    cachable      Always set to ACL_NOT_CACHABLE.
 *    subject       Subject property list
 *    resource      Resource property list
 *    auth_info     Authentication info, if any
 *  RETURNS
 *    retcode       The usual LAS return codes.
 */
int LASIsLockOwnerEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
                       char *attr_pattern, ACLCachable_t *cachable,
                       void **LAS_cookie, PList_t subject, PList_t resource,
                       PList_t auth_info, PList_t global_auth)
{
    int retcode=0;
    int matched=0;
    char *lock_owner=NULL;
    char *user=NULL;
    PRBool pattern=PR_TRUE;
    int rv=0;

    *cachable = ACL_NOT_CACHABLE;
    *LAS_cookie = (void *)0;

    if (strcmp(attr_name, ACL_ATTR_IS_LOCK_OWNER)) {
        nserrGenerate(errp, ACLERRINVAL, ACLERR6700, ACL_Program, 2,
                      XP_GetAdminStr(DBT_lasIsLockOwnerEvalReceivedRequestForAtt_),
                      attr_name);
        return LAS_EVAL_INVALID;
    }

    if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
        nserrGenerate(errp, ACLERRINVAL, ACLERR6710, ACL_Program, 2,
                      XP_GetAdminStr(DBT_lasIsLockOwnerEvalIllegalComparatorDN_),
                      comparator_string(comparator));
        return LAS_EVAL_INVALID;
    }

   if (PL_strcasecmp(attr_pattern, "on") == 0 ||
       PL_strcasecmp(attr_pattern, "true") == 0 ||
       PL_strcasecmp(attr_pattern, "yes") == 0 ||
       PL_strcasecmp(attr_pattern, "1") == 0) {
        pattern = PR_TRUE;
    }
    else if (PL_strcasecmp(attr_pattern, "off") == 0 ||
        PL_strcasecmp(attr_pattern, "false") == 0 ||
        PL_strcasecmp(attr_pattern, "no") == 0 ||
        PL_strcasecmp(attr_pattern, "0") == 0) {
        pattern = PR_FALSE;
    } else {
        nserrGenerate(errp, ACLERRINVAL, ACLERR6720, ACL_Program, 2,
                      XP_GetAdminStr(DBT_lasIsLockOwnerEvalIllegalAttrPattern_),
                      attr_pattern);
        return LAS_EVAL_INVALID;
    }

    // get the lock owner 
    // assuming lock owner has been set in plist before ACL_Evaluate is called
    rv = ACL_GetAttribute(errp, ACL_ATTR_LOCK_OWNER, (void **)&lock_owner, 
                          subject, resource, auth_info, global_auth);
    if (rv != LAS_EVAL_TRUE) {
        return rv;
    }

    if (lock_owner) {
        // get the authenticated user name
        rv = ACL_GetAttribute(errp, ACL_ATTR_USER, (void **)&user, 
                              subject, resource, auth_info, global_auth);
        if (rv != LAS_EVAL_TRUE) {
            return rv;
        }
        if (user) {
            // if user is the lock owner
            matched = !strcmp(user, lock_owner);
        } else // user has not been authenticated yet
            matched=0;
    } else // lock owner is null means does not match
        matched=0;

    if (pattern == PR_FALSE)
        matched = !matched;
    if (comparator == CMP_OP_EQ) {
        retcode = (matched ? LAS_EVAL_TRUE : LAS_EVAL_FALSE);
    } else {
        retcode = (matched ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
    }

    ereport(LOG_VERBOSE,
            "acl is-lock-owner : user [%s] %s is lock owner [%s] %s (%s)",
            user?user:"",
            (retcode == LAS_EVAL_FALSE) ? "does not match"
            : (retcode == LAS_EVAL_TRUE) ? "matched" : "error in",
            lock_owner?lock_owner:"",
            (comparator == CMP_OP_EQ) ? "=" : "!=",
            attr_pattern);

    return retcode;
}
Beispiel #8
0
/*
 *	LASDnsEval
 *	INPUT
 *	attr_name	The string "dns" - in lower case.
 *	comparator	CMP_OP_EQ or CMP_OP_NE only
 *	attr_pattern	A comma-separated list of DNS names
 *			Any segment(s) in a DNS name can be wildcarded using
 *			"*".  Note that this is not a true Regular Expression
 *			form.
 *	*cachable	Always set to ACL_INDEF_CACHE
 *      subject		Subject property list
 *      resource 	Resource property list
 *      auth_info	Authentication info, if any
 *	RETURNS
 *	ret code	The usual LAS return codes.
 */
int LASDnsEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
               char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie,
               PList_t subject, PList_t resource,
               PList_t auth_info, PList_t global_auth)
{
    int			result;
    int			aliasflg;
    char		*my_dns;
    LASDnsContext_t 	*context = NULL;
    int			rv;

    *cachable = ACL_INDEF_CACHABLE;

    if (strcmp(attr_name, "dns") == 0) {
        /* Enable aliasflg for "dns", which allows "dns" hostname to look up
         * DSN hash table using the primary hostname. */
        aliasflg = 1;
    } else if (strcmp(attr_name, "dnsalias") == 0) {
        aliasflg = 1;
    } else {
        nserrGenerate(errp, ACLERRINVAL, ACLERR4800, ACL_Program, 2, XP_GetAdminStr(DBT_lasDnsBuildReceivedRequestForAtt_), attr_name);
        return LAS_EVAL_INVALID;
    }

    if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
        nserrGenerate(errp, ACLERRINVAL, ACLERR4810, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsevalIllegalComparatorDN_), comparator_string(comparator));
        return LAS_EVAL_INVALID;
    }

    /* If this is the first time through, build the pattern tree first.  */
    if (*LAS_cookie == NULL) {
        ACL_CritEnter();
        if (*LAS_cookie == NULL) {	/* Must check again */
            *LAS_cookie = context =
                              (LASDnsContext_t *)PERM_MALLOC(sizeof(LASDnsContext_t));
            if (context == NULL) {
                nserrGenerate(errp, ACLERRNOMEM, ACLERR4820, ACL_Program, 1, XP_GetAdminStr(DBT_lasdnsevalUnableToAllocateContex_));
                ACL_CritExit();
                return LAS_EVAL_FAIL;
            }
            context->Table = NULL;
            if (LASDnsBuild(errp, attr_pattern, context, aliasflg) ==
                    LAS_EVAL_INVALID) {
                /* Error is already printed in LASDnsBuild */
                ACL_CritExit();
                return LAS_EVAL_FAIL;
            }
            /* After this line, it is assured context->Table is not NULL. */
        } else {
            context = (LASDnsContext *) *LAS_cookie;
        }
        ACL_CritExit();
    } else {
        ACL_CritEnter();
        context = (LASDnsContext *) *LAS_cookie;
        ACL_CritExit();
    }

    /* Call the DNS attribute getter */
#ifdef  UTEST
    LASDnsGetDns(&my_dns);      /* gets stuffed on return       */
#else
    rv = ACL_GetAttribute(errp, ACL_ATTR_DNS, (void **)&my_dns,
                          subject, resource, auth_info, global_auth);

    if (rv != LAS_EVAL_TRUE) {
        if (subject || resource) {
            char rv_str[16];
            /* Don't ereport if called from ACL_CachableAclList */
            sprintf(rv_str, "%d", rv);
            nserrGenerate(errp, ACLERRINVAL, ACLERR4830, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsevalUnableToGetDnsErrorDN_), rv_str);
        }
        return LAS_EVAL_FAIL;
    }
#endif

    result = LASDnsMatch(my_dns, context);

    if (comparator == CMP_OP_NE) {
        if (result == LAS_EVAL_FALSE)
            return LAS_EVAL_TRUE;
        else if (result == LAS_EVAL_TRUE)
            return LAS_EVAL_FALSE;
    }
    return (result);
}
Beispiel #9
0
/*  LASDNSBuild
 *  Builds a hash table of all the hostnames provided (plus their aliases
 *  if aliasflg is true).  Wildcards are only permitted in the leftmost
 *  field.  They're represented in the hash table by a leading period.
 *  E.g. ".mcom.com".
 *
 *  RETURNS	Zero on success, else LAS_EVAL_INVALID
 */
int
LASDnsBuild(NSErr_t *errp, char *attr_pattern, LASDnsContext_t *context, int aliasflg)
{
    size_t delimiter; /* length of valid tokeni */
    char token[256];  /* max length dns name */
    int i;
    char **p;
    pool_handle_t *pool;
    PRStatus error=PR_SUCCESS;
    char	buffer[PR_NETDB_BUF_SIZE];
#ifdef	UTEST
    struct hostent *he, host;
#else
    PRHostEnt *he, host;
#endif
    char *end_attr_pattern;

    if (attr_pattern == NULL) {
        nserrGenerate(errp, ACLERRINVAL, ACLERR4770, ACL_Program, 1,
                      XP_GetAdminStr(DBT_lasdnsbuildInvalidAttributePattern_));
        return LAS_EVAL_INVALID;
    }

    context->Table = PR_NewHashTable(0,
                                     PR_HashCaseString,
                                     PR_CompareCaseStrings,
                                     PR_CompareValues,
                                     &ACLPermAllocOps,
                                     NULL);
    pool = pool_create();
    context->pool = pool;
    if ((!context->Table) || (!context->pool)) {
        nserrGenerate(errp, ACLERRNOMEM, ACLERR4700, ACL_Program, 1,
                      XP_GetAdminStr(DBT_lasdnsbuildUnableToAllocateHashT_));
        return LAS_EVAL_INVALID;
    }

    end_attr_pattern = attr_pattern + strlen(attr_pattern);
    do {
        size_t maxsize = sizeof(token);
        /*  Get a single hostname from the pattern string        */
        delimiter = strcspn(attr_pattern, ", \t");
        if (delimiter >= maxsize) {
            delimiter = maxsize-1;
        }
        PL_strncpyz(token, attr_pattern, delimiter + 1);
        token[delimiter] = '\0';

        /*  Skip any white space after the token                 */
        attr_pattern += delimiter;
        if (attr_pattern < end_attr_pattern) {
            attr_pattern += strspn(attr_pattern, ", \t");
        }

        /*  If there's a wildcard, strip it off but leave the "."
         *  Can't have aliases for a wildcard pattern.
         *  Treat "*" as a special case.  If so, go ahead and hash it.
         */
        if (token[0] == '*') {
            if (token[1] != '\0') {
                if (!PR_HashTableAdd(context->Table, pool_strdup(pool, &token[1]), (void *)-1)) {
                    nserrGenerate(errp, ACLERRFAIL, ACLERR4710, ACL_Program, 2,
                                  XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), token);
                    return LAS_EVAL_INVALID;
                }
            } else {
                if (!PR_HashTableAdd(context->Table, pool_strdup(pool, token), (void *)-1)) {
                    nserrGenerate(errp, ACLERRFAIL, ACLERR4720, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), token);
                    return LAS_EVAL_INVALID;
                }
            }
        } else  {
            /*  This is a single hostname add it to the hash table        */
            if (!PR_HashTableAdd(context->Table, pool_strdup(pool, &token[0]), (void *)-1)) {
                nserrGenerate(errp, ACLERRFAIL, ACLERR4730, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), token);
                return LAS_EVAL_INVALID;
            }

            if (aliasflg) {
                void *iter = NULL;
                int addrcnt = 0;
                PRNetAddr *netaddr = (PRNetAddr *)PERM_CALLOC(sizeof(PRNetAddr));
                PRAddrInfo *infop = PR_GetAddrInfoByName(token,
                                    PR_AF_UNSPEC, (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME));
                if (!netaddr) {
                    if (infop) {
                        PR_FreeAddrInfo(infop);
                    }
                    return LAS_EVAL_NEED_MORE_INFO; /* hostname not known to dns? */
                }
                if (!infop) {
                    if (netaddr) {
                        PERM_FREE(netaddr);
                    }
                    return LAS_EVAL_NEED_MORE_INFO; /* hostname not known to dns? */
                }
                /* need to count the address, first */
                while ((iter = PR_EnumerateAddrInfo(iter, infop, 0, netaddr))) {
                    addrcnt++;
                }
                if (0 == addrcnt) {
                    PERM_FREE(netaddr);
                    PR_FreeAddrInfo(infop);
                    return LAS_EVAL_NEED_MORE_INFO; /* hostname not known to dns? */
                }
                iter = NULL; /* from the beginning */
                memset(netaddr, 0, sizeof(PRNetAddr));
                for (i = 0; i < addrcnt; i++) {
                    iter = PR_EnumerateAddrInfo( iter, infop, 0, netaddr );
                    if (NULL == iter) {
                        break;
                    }
                    error = PR_GetHostByAddr(netaddr, buffer,
                                             PR_NETDB_BUF_SIZE, &host);
                    if (error == PR_SUCCESS) {
                        he = &host;
                    } else {
                        continue;
                    }
                    if (he->h_name) {
                        /* Add it to the hash table */
                        if (!PR_HashTableAdd(context->Table,
                                             pool_strdup(pool, he->h_name),
                                             (void *)-1)) {
                            nserrGenerate(errp, ACLERRFAIL, ACLERR4750,
                                          ACL_Program, 2,
                                          XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_),
                                          he->h_name);
                            PERM_FREE(netaddr);
                            PR_FreeAddrInfo(infop);
                            return LAS_EVAL_INVALID;
                        }
                    }

                    if (he->h_aliases && he->h_aliases[0]) {
                        for (p = he->h_aliases; *p; ++p) {
                            /* Add it to the hash table */
                            if (!PR_HashTableAdd(context->Table,
                                                 pool_strdup(pool, *p),
                                                 (void *)-1)) {
                                nserrGenerate(errp, ACLERRFAIL, ACLERR4760,
                                              ACL_Program, 2,
                                              XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_),
                                              *p);
                                PERM_FREE(netaddr);
                                PR_FreeAddrInfo(infop);
                                return LAS_EVAL_INVALID;
                            }
                        }
                    }
                } /* for (i = 0; i < addrcnt; i++) */
                PERM_FREE(netaddr);
                PR_FreeAddrInfo(infop);
            } /* if aliasflg */
        } /* else - single hostname */
    } while ((attr_pattern != NULL) &&
             (attr_pattern[0] != '\0') &&
             (delimiter != 0));

    return 0;
}
Beispiel #10
0
NSAPI_PUBLIC int
ACL_ListPostParseForAuth(NSErr_t *errp, ACLListHandle_t *acl_list ) 
{
    ACLHandle_t *acl;
    ACLWrapper_t *wrap;
    ACLExprHandle_t *expr;
    char *method;
    char *database;
    int rv;
    ACLDbType_t *dbtype;
    ACLMethod_t *methodtype;

    if ( acl_list == NULL )
        return(0);

    for ( wrap = acl_list->acl_list_head; wrap; wrap = wrap->wrap_next ) {

        acl = wrap->acl;
        if ( acl == NULL )
            continue;

        for ( expr = acl->expr_list_head; expr; expr = expr->expr_next ) {

            if ( expr->expr_type != ACL_EXPR_TYPE_AUTH || 
                 expr->expr_auth == NULL) 
                continue;

            rv = PListGetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, 
                                (void **) &method, NULL);
            if ( rv >= 0 ) {
		methodtype = (ACLMethod_t *)PERM_MALLOC(sizeof(ACLMethod_t));
		rv = ACL_MethodFind(errp, method, methodtype);
		if (rv) {
		    nserrGenerate(errp, ACLERRUNDEF, ACLERR3800, ACL_Program,
				  3, acl->tag, "method", method);
		    PERM_FREE(methodtype);
		    return(ACLERRUNDEF);
		}

	        rv = PListSetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, 
				      methodtype, NULL);
		if ( rv < 0 ) {
		    nserrGenerate(errp, ACLERRNOMEM, ACLERR3810, ACL_Program,
				  0);
		    return(ACLERRNOMEM);
		}
		PERM_FREE(method);
	    }
    
            rv = PListGetValue(expr->expr_auth, ACL_ATTR_DATABASE_INDEX, 
				(void **) &database, NULL);

	    if (rv < 0) continue;

	    /* The following function lets user use databases which are
	     * not registered by their administrators.  This also fixes
	     * the backward compatibility.
	     */
	    dbtype = (ACLDbType_t *)PERM_MALLOC(sizeof(ACLDbType_t));
	    rv = ACL_RegisterDbFromACL(errp, (const char *) database,
				       dbtype);

	    if (rv < 0) {
		    nserrGenerate(errp, ACLERRUNDEF, ACLERR3800, ACL_Program,
				  3, acl->tag, "database", database);
		PERM_FREE(dbtype);
		return(ACLERRUNDEF);
	    }
    
	    rv = PListInitProp(expr->expr_auth, ACL_ATTR_DBTYPE_INDEX, ACL_ATTR_DBTYPE, 
			       dbtype, NULL);
	    if ( rv < 0 ) {
		nserrGenerate(errp, ACLERRNOMEM, ACLERR3810, ACL_Program,
			      0);
		return(ACLERRNOMEM);
	    }

        }

    }

    return(0);

}
Beispiel #11
0
/*
 *  LASUserEval
 *    INPUT
 *	attr_name	The string "user" - in lower case.
 *	comparator	CMP_OP_EQ or CMP_OP_NE only
 *	attr_pattern	A comma-separated list of users
 *	*cachable	Always set to ACL_NOT_CACHABLE.
 *      subject		Subject property list
 *      resource        Resource property list
 *      auth_info	Authentication info, if any
 *    RETURNS
 *	retcode	        The usual LAS return codes.
 */
int LASUserEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, 
		char *attr_pattern, ACLCachable_t *cachable,
                void **LAS_cookie, PList_t subject, PList_t resource,
                PList_t auth_info, PList_t global_auth)
{
    char	    *uid;
    char	    *users;
    char	    *user;
    char	    *comma;
    int		    retcode;
    int		    matched;
    int		    is_owner;
    int		    rv;

    *cachable = ACL_NOT_CACHABLE;
    *LAS_cookie = (void *)0;

    if (strcmp(attr_name, ACL_ATTR_USER) != 0) {
	nserrGenerate(errp, ACLERRINVAL, ACLERR5700, ACL_Program, 2, XP_GetAdminStr(DBT_lasUserEvalReceivedRequestForAtt_), attr_name);
	return LAS_EVAL_INVALID;
    }

    if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
	nserrGenerate(errp, ACLERRINVAL, ACLERR5710, ACL_Program, 2, XP_GetAdminStr(DBT_lasuserevalIllegalComparatorDN_), comparator_string(comparator));
	return LAS_EVAL_INVALID;
    }

    if (!strcmp(attr_pattern, "anyone")) {
        *cachable = ACL_INDEF_CACHABLE;
	return comparator == CMP_OP_EQ ? LAS_EVAL_TRUE : LAS_EVAL_FALSE;
    }

    /* get the authenticated user name */
#ifndef	UTEST

    rv = ACL_GetAttribute(errp, ACL_ATTR_USER, (void **)&uid,
			  subject, resource, auth_info, global_auth);

    if (rv != LAS_EVAL_TRUE) {
	return rv;
    }
#else
    uid	= (char *)LASUserGetUser();
#endif

    /* We have an authenticated user */
    if (!strcmp(attr_pattern, "all")) {
	return comparator == CMP_OP_EQ ? LAS_EVAL_TRUE : LAS_EVAL_FALSE;
    }

    users = STRDUP(attr_pattern);

    if (!users) {
	nserrGenerate(errp, ACLERRNOMEM, ACLERR5720, ACL_Program, 1,
	XP_GetAdminStr(DBT_lasuserevalRanOutOfMemoryN_));
	return LAS_EVAL_FAIL;
    }

    user = users;
    matched = 0;

    /* check if the uid is one of the users */
    while(user != 0 && *user != 0 && !matched) {
	if ((comma = strchr(user, ',')) != NULL) {
	    *comma++ = 0;
	}

	/* ignore leading whitespace */
	while(*user == ' ' || *user == '\t') user++;

	if (*user) {
	    /* ignore trailing whitespace */
	    int len = strlen(user);
	    char *ptr = user+len-1;

	    while(*ptr == ' ' || *ptr == '\t') *ptr-- = 0;
	}

	if (!strcasecmp(user, ACL_ATTR_OWNER)) {
	    rv = ACL_GetAttribute(errp, ACL_ATTR_IS_OWNER, (void **)&is_owner,
				  subject, resource, auth_info, global_auth);
	    if (rv == LAS_EVAL_TRUE)
		matched = 1;
	    else
		/* continue checking for next user */
		user = comma;
	}
	else if (!WILDPAT_CASECMP(uid, user)) {
	    /* uid is one of the users */
	    matched = 1;
	}
	else {
	    /* continue checking for next user */
	    user = comma;
	}
    }

    if (comparator == CMP_OP_EQ) {
	retcode = (matched ? LAS_EVAL_TRUE : LAS_EVAL_FALSE);
    }
    else {
	retcode = (matched ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
    }

    FREE(users);
    return retcode;
}
/*	SSL LAS driver
 *	Note that everything is case-insensitive.
 *	INPUT
 *	attr		must be the string "ssl".
 *	comparator	can only be "=" or "!=".
 *	pattern		"on", "off", "yes", "no", "true", "false", "1", "0"
 *	OUTPUT
 *	cachable	Will be set to ACL_NOT_CACHABLE.
 *	return code	set to LAS_EVAL_*
 */
int
LASSSLEval(NSErr_t *errp, char *attr, CmpOp_t comparator, char *pattern, 
		 ACLCachable_t *cachable, void **las_cookie, PList_t subject, 
		 PList_t resource, PList_t auth_info, PList_t global_auth)
{
    Session *sn = NULL;
    PRBool sslrequired, sslstate;
    int rv;
    
    /*	Sanity checking				*/
    if (strcmp(attr, "ssl") != 0) {
        nserrGenerate(errp, ACLERRINVAL, ACLERR6300, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasUnexpectedAttribute), attr);
        return LAS_EVAL_INVALID;
    }
    if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
        nserrGenerate(errp, ACLERRINVAL, ACLERR6310, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasIllegalComparator), comparator_string(comparator));
        return LAS_EVAL_INVALID;
    }
    *cachable = ACL_NOT_CACHABLE;       // ????

    if (PL_strcasecmp(pattern, "on") == 0 ||
        PL_strcasecmp(pattern, "true") == 0 ||
        PL_strcasecmp(pattern, "yes") == 0 ||
        PL_strcasecmp(pattern, "1") == 0)
    {
        sslrequired = PR_TRUE;
    }
    else
    if (PL_strcasecmp(pattern, "off") == 0 ||
        PL_strcasecmp(pattern, "false") == 0 ||
        PL_strcasecmp(pattern, "no") == 0 ||
        PL_strcasecmp(pattern, "0") == 0)
    {
        sslrequired = PR_FALSE;
    }
    else {
        nserrGenerate(errp, ACLERRINVAL, ACLERR6320, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasIllegalValue), pattern);
        return LAS_EVAL_INVALID;
    }

    // Now look whether our session is over SSL
    if (PListGetValue(subject, ACL_ATTR_SESSION_INDEX, (void **)&sn, NULL) < 0) {
        nserrGenerate(errp, ACLERRINVAL, ACLERR6330, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasUnableToGetSessionAddr));
        return LAS_EVAL_FAIL;
    }

    sslstate = GetSecurity(sn);

    if ((sslstate == sslrequired) && (comparator == CMP_OP_EQ)) {
        rv = LAS_EVAL_TRUE;
    }
    else if ((sslstate != sslrequired) && (comparator == CMP_OP_NE)) {
        rv = LAS_EVAL_TRUE;
    } else {
        rv = LAS_EVAL_FALSE;
    }

    ereport(LOG_VERBOSE, "acl ssl: %s on ssl %s (%s)",
            (rv == LAS_EVAL_FALSE) ? "no match" : "match",
            (comparator == CMP_OP_EQ) ? "=" : "!=",
            pattern);

    return rv;
}
//
// 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;
}