Exemplo n.º 1
0
NSAPI_PUBLIC int
ACL_ExprSetDenyWith( NSErr_t *errp, ACLExprHandle_t *expr, char *deny_type, char *deny_response)
{
int rv;

    if ( expr->expr_argc == 0 ) {
       if ( (rv = ACL_ExprAddArg(errp, expr, deny_type)) < 0 ) 
           return(rv);
       if ( (rv = ACL_ExprAddArg(errp, expr, deny_response)) < 0 ) 
           return(rv);
    } else if ( expr->expr_argc == 2 ) {
       if ( deny_type ) {
           if ( expr->expr_argv[0] ) 
               PERM_FREE(expr->expr_argv[0]);
           expr->expr_argv[0] = PERM_STRDUP(deny_type);
           if ( expr->expr_argv[0] == NULL )
               return(ACLERRNOMEM);
       }
       if ( deny_response ) {
           if ( expr->expr_argv[1] ) 
               PERM_FREE(expr->expr_argv[1]);
           expr->expr_argv[1] = PERM_STRDUP(deny_response);
           if ( expr->expr_argv[0] == NULL )
               return(ACLERRNOMEM);
       }
    } else {
        return(ACLERRINTERNAL);
    }
    return(0);
}
Exemplo n.º 2
0
NSAPI_PUBLIC int
ACL_ExprAddArg( NSErr_t *errp, 
    ACLExprHandle_t *expr, 
    const char *arg )
{

    if ( expr == NULL ) 
        return(ACLERRUNDEF);

    if (expr->expr_argv == NULL)
        expr->expr_argv = (char **) PERM_MALLOC( 2 * sizeof(char *) );
    else
        expr->expr_argv = (char **) PERM_REALLOC( expr->expr_argv,
                                        (expr->expr_argc+2)
                                        * sizeof(char *) );
    
    if (expr->expr_argv == NULL) 
        return(ACLERRNOMEM);
    
    expr->expr_argv[expr->expr_argc] = PERM_STRDUP( arg );
    if (expr->expr_argv[expr->expr_argc] == NULL) 
        return(ACLERRNOMEM);
    expr->expr_argc++;
    expr->expr_argv[expr->expr_argc] = NULL;
    
    return(0);

}
Exemplo n.º 3
0
/*
 * Gets a name list of consisting of all ACL names for input list. 
 *
 * Input:
 *	acl_list	an ACL List handle	
 *	name_list	pointer to a list of string pointers	
 * Returns:
 *    0			success
 *    < 0		failure
 */
NSAPI_PUBLIC int
ACL_ListGetNameList(NSErr_t *errp, ACLListHandle_t *acl_list, char ***name_list)
{
    const int block_size = 50;
    ACLWrapper_t 	*wrapper;
    int			list_index;
    int			list_size;
    char		**tmp_list;
    char		**local_list;
    const char		*name;
    

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

    list_size = block_size;
    local_list = (char **) PERM_MALLOC(sizeof(char *) * list_size);
    if ( local_list == NULL ) 
        return(ACLERRNOMEM); 
    list_index = 0;
    local_list[list_index] = NULL; 

    for ( wrapper = acl_list->acl_list_head; wrapper != NULL; 
                        wrapper = wrapper->wrap_next ) {
        if ( wrapper->acl->tag ) 
            name = wrapper->acl->tag;
        else 
            name = "noname";
        if ( list_index + 2 > list_size ) {
            list_size += block_size;
            tmp_list = (char **) PERM_REALLOC(local_list, 
                                              sizeof(char *) * list_size);
            if ( tmp_list == NULL ) {
                ACL_NameListDestroy(errp, local_list);
                return(ACLERRNOMEM); 
            }
            local_list = tmp_list;
        } 
        local_list[list_index] = PERM_STRDUP(name);
        if ( local_list[list_index] == NULL ) {
            ACL_NameListDestroy(errp, local_list);
            return(ACLERRNOMEM); 
        }
        list_index++;
        local_list[list_index] = NULL; 
    }    
    *name_list = local_list;
    return(0);
}
Exemplo n.º 4
0
NSAPI_PUBLIC ACLHandle_t *
ACL_AclNew(NSErr_t *errp, char *tag )
{
ACLHandle_t *handle;

    handle = ( ACLHandle_t * ) PERM_CALLOC ( 1 * sizeof (ACLHandle_t) );
    if ( handle && tag ) {
        handle->tag = PERM_STRDUP( tag );    
        if ( handle->tag == NULL ) {
            PERM_FREE(handle);
            return(NULL);
        }
    }
    return(handle);
}
NSAPI_PUBLIC dns_cache_entry_t *
dns_cache_insert(char *host, unsigned int ip, unsigned int verified)
{
	dns_cache_entry_t *newentry;

	if ( !dns_cache || !ip)  {
		return NULL;
    }

	if ( (newentry = (dns_cache_entry_t *)PERM_MALLOC(sizeof(dns_cache_entry_t))) == NULL) {
		ereport(LOG_FAILURE, XP_GetAdminStr(DBT_dnsCacheInsertErrorAllocatingEnt_));
		goto error;
	}

	if (host) {
		if ( (newentry->host = PERM_STRDUP(host)) == NULL) {
			ereport(LOG_FAILURE, XP_GetAdminStr(DBT_dnsCacheInsertMallocFailure_));
			goto error;
		}
	} else
		newentry->host = NULL;

#ifdef CACHE_DEBUG
	newentry->cache.magic = CACHE_ENTRY_MAGIC;
#endif

	newentry->ip = ip;
	newentry->verified = verified;

	newentry->last_access = ft_time();

	if ( cache_insert_p(dns_cache, &(newentry->cache), (void *)&(newentry->ip), 
		(void *)newentry, &dns_cache_entry_functions) < 0) {
		/* Not a bad error; it just means the cache is full */
		goto error;
	}

	return newentry;

error:
	if (newentry) {
		if (newentry->host)
			PERM_FREE(newentry->host);
		PERM_FREE(newentry);
	}
	return NULL;
}
Exemplo n.º 6
0
NSAPI_PUBLIC int 
ACL_AddPermInfo( NSErr_t *errp, ACLHandle_t *acl,
        char **access_rights,
        PFlags_t flags,
        int allow,
        ACLExprHandle_t *expr,
        char *tag )
{
    if ( acl == NULL || expr == NULL ) 
        return(ACLERRUNDEF);
    
    expr->expr_flags = flags;
    expr->expr_argv = (char **) access_rights;
    expr->expr_tag = PERM_STRDUP( tag );
    if ( expr->expr_tag == NULL )
        return(ACLERRNOMEM);
    return(ACL_ExprAppend( errp, acl, expr ));
}
Exemplo n.º 7
0
static Symbol_t *
acl_sym_new(ACLHandle_t *acl)
{
    Symbol_t *sym;
    /* It's not there, so add it */
    sym = (Symbol_t *) PERM_MALLOC(sizeof(Symbol_t));
    if ( sym == NULL ) 
        return(NULL);

    sym->sym_name = PERM_STRDUP(acl->tag);
    if ( sym->sym_name == NULL ) {
        PERM_FREE(sym);
        return(NULL);
    }

    sym->sym_type = ACLSYMACL;
    sym->sym_data = (void *) acl;
    return(sym);

}
Exemplo n.º 8
0
static int 
_fsmutex_create(fsmutex_s *fsm, char *name, int number)
{
    char tn[256];
    SYS_FILE lfd;
    int visible = (fsm->flags & FSMUTEX_VISIBLE ? 1 : 0);

    util_snprintf(tn, 256, "/tmp/%s.%d", name, number);
    if(!visible)
        unlink(tn);
    if( (lfd = PR_Open(tn, PR_RDWR|PR_CREATE_FILE, 0644)) == NULL)
        return -1;

    if(!visible)
        unlink(tn);
    else
        fsm->id = PERM_STRDUP(tn);
    fsm->mutex = lfd;
    return 0;
}
PR_END_EXTERN_C


/* ----------------------------- filter_fill ------------------------------ */

static Filter *filter_fill(const char *name, int order, const FilterMethods *methods, int flags, Filter *filter)
{
    filter->name = PERM_STRDUP(name);
    filter->flags = flags;
    filter->order = order & FILTER_MASK; // Reserve topmost bits for future use

    /*
     * Setup NSAPI-specific filter methods
     */

    if (methods->insert) {
        filter->insert = methods->insert;
    } else {
        filter->insert = &filtermethod_always_insert;
    }

    if (methods->remove) {
        filter->remove = methods->remove;
    } else {
        filter->remove = &filtermethod_default_remove;
    }

    if (methods->read) {
        filter->read = methods->read;
    } else {
        filter->read = NULL;
    }

    /*
     * Setup NSPR filter methods
     */

    filter->priomethods = *PR_GetDefaultIOMethods();
    filter->priomethods.file_type = PR_DESC_LAYERED;

    // Assert NSPR IO layer and NSAPI filter binary compatibility
    PR_ASSERT(sizeof(PRSendFileData) == sizeof(sendfiledata));
    PR_ASSERT(sizeof(PRIOVec) == sizeof(NSAPIIOVec));
    PR_ASSERT(sizeof(PRStatus) == sizeof(int));
    PR_ASSERT(sizeof(PRInt32) == sizeof(int));
    PR_ASSERT(sizeof(PRSize) == sizeof(size_t));

    filter->priomethods.close = &filtermethod_close;

    if (methods->flush) {
        filter->priomethods.fsync = (PRFsyncFN)methods->flush;
    } else {
        filter->priomethods.fsync = &filtermethod_default_fsync;
    }

    if (methods->read) {
        filter->priomethods.read = &filtermethod_emulate_read;
        filter->priomethods.recv = &filtermethod_emulate_recv;
    } else {
        filter->priomethods.read = &filtermethod_default_read;
        filter->priomethods.recv = &filtermethod_default_recv;
    }

    if (methods->write) {
        filter->priomethods.write = (PRWriteFN)methods->write;
        filter->priomethods.send = (PRSendFN)methods->write;
    } else {
        filter->priomethods.write = &filtermethod_default_write;
        filter->priomethods.send = &filtermethod_default_send;
    }

    if (methods->writev) {
        filter->priomethods.writev = (PRWritevFN)methods->writev;
    } else if (methods->write) {
        ereport(LOG_VERBOSE, "Emulating writev for filter %s", filter->name);
        filter->priomethods.writev = &filtermethod_emulate_writev;
    } else {
        filter->priomethods.writev = &filtermethod_default_writev;
    }

    if (methods->sendfile) {
        filter->priomethods.sendfile = (PRSendfileFN)methods->sendfile;
    } else if (methods->write) {
        ereport(LOG_VERBOSE, "Emulating sendfile for filter %s", filter->name);
        filter->priomethods.sendfile = &filtermethod_emulate_sendfile;
    } else {
        filter->priomethods.sendfile = &filtermethod_default_sendfile;
    }

    /*
     * Add the filter to the front of the server-wide list
     */

    PR_Lock(_filter_list_lock);

    filter->next = _filter_list;
    _filter_list = filter;

    _filter_hash.remove((void *)filter->name);
    _filter_hash.insert((void *)filter->name, filter);

    PR_Unlock(_filter_list_lock);

    return filter;
}
Exemplo n.º 10
0
NSAPI_PUBLIC int 
ACL_ExprTerm( NSErr_t *errp, ACLExprHandle_t *acl_expr,
        const char *attr_name,
        CmpOp_t cmp, 
        char *attr_pattern )
{
ACLExprEntry_t	*expr;
ACLExprRaw_t	*raw_expr;

    if ( acl_expr == NULL || acl_expr->expr_arry == NULL )
        return(ACLERRUNDEF);

    if ( acl_expr->expr_term_index >= acl_expr->expr_arry_size  ) {
        acl_expr->expr_arry = ( ACLExprEntry_t *) 
            PERM_REALLOC ( acl_expr->expr_arry, 
			   (acl_expr->expr_arry_size + ACL_TERM_BSIZE)
			   * sizeof(ACLExprEntry_t));
        if ( acl_expr->expr_arry == NULL )
            return(ACLERRNOMEM); 
        acl_expr->expr_arry_size += ACL_TERM_BSIZE;
    }

    expr = &acl_expr->expr_arry[acl_expr->expr_term_index];
    acl_expr->expr_term_index++;
    
    expr->attr_name = PERM_STRDUP(attr_name);
    if ( expr->attr_name == NULL )
        return(ACLERRNOMEM);
    expr->comparator = cmp; 
    expr->attr_pattern = PERM_STRDUP(attr_pattern);
    if ( expr->attr_pattern == NULL )
        return(ACLERRNOMEM);
    expr->true_idx = ACL_TRUE_IDX;
    expr->false_idx = ACL_FALSE_IDX;
    expr->start_flag = 1;
    expr->las_cookie = 0;
    expr->las_eval_func = 0;

    if ( acl_expr->expr_raw_index >= acl_expr->expr_raw_size  ) {
        acl_expr->expr_raw = ( ACLExprRaw_t *) 
            PERM_REALLOC ( acl_expr->expr_raw, 
			   (acl_expr->expr_raw_size + ACL_TERM_BSIZE)
			   * sizeof(ACLExprRaw_t));
        if ( acl_expr->expr_raw == NULL )
            return(ACLERRNOMEM); 
        acl_expr->expr_raw_size += ACL_TERM_BSIZE;
    }
    
    raw_expr = &acl_expr->expr_raw[acl_expr->expr_raw_index];
    acl_expr->expr_raw_index++;

    raw_expr->attr_name = expr->attr_name;
    raw_expr->comparator = cmp;
    raw_expr->attr_pattern = expr->attr_pattern;
    raw_expr->logical = (ACLExprOp_t)0;

#ifdef DEBUG_LEVEL_2
    printf ( "%d: %s %s %s, t=%d, f=%d\n",
            acl_expr->expr_term_index - 1,
            expr->attr_name,
            acl_comp_string( expr->comparator ),
            expr->attr_pattern,
            expr->true_idx,
            expr->false_idx );
#endif

    return(0);
}
/** **************************************************************************
 * check-request-limits SAF
 *
 * See top of this file for the pb parameters this SAF can consume and the
 * defaults for each.
 *
 * This SAF counts requests per interval for the given monitor/bucket. If
 * the request/sec in an interval exceeds the max-rps given then it returns
 * REQ_ABORTED for this and all subsequent matching requests in the current
 * interval. After the next interval request rate recomputation the request
 * limiting may be discontinued if the conditions of 'continue' are met.
 *
 * Separately, concurrent requests for the same bucket may be limited to
 * the given number if max-connections is given.
 *
 * On the next request after purge_timeout, a purge sweep of the buckets is
 * done, deleting any entries which have not seen any recomputes in the 
 * purge interval (unless timeout disabled by setting it to zero).
 *
 * For more information, refer to the WS7.0 security functional spec at:
 * http://sac.eng/arc/WSARC/2004/076/
 *
 * For params: http://docs.sun.com/source/817-1835-10/npgmysaf.html#wp14889
 * For returns: http://docs.sun.com/source/817-1835-10/npgmysaf.html#wp14969
 *
 * This returns:
 *      REQ_NOACTION: If the request can go on.
 *      REQ_ABORTED: If the request has hit limits and is not to be processed.
 *          Return code is set to 'error' param (default 503).
 *
 */
int check_request_limits(pblock *pb, Session *sn, Request *rq)
{
    const char * param;
    int response = REQ_NOACTION;

    if (rq->rq_attr.req_restarted) {
        // Do not count restarted requests as new requests for the
        // purpose of reqlimit accounting as it is just one client
        // request.  (This is particularly important for
        // max-connections since processing restarts would cause the
        // conc counter to increase more than once for a given request
        // but only decrease once at the end).
        return response;
    }

    time_t time_now = rq->req_start;
    assert (time_now != NULL);

    // Get max-rps
    
    int max_rps = 0;
    param = pblock_findval(MAXRPS_PARAM, pb);
    if (param) {
        max_rps = atoi(param);
    }

    // Get max-connections

    int conc = 0;
    param = pblock_findval(CONC_PARAM, pb);
    if (param) {
        conc = atoi(param);
    }

    // We must have at least max-rps or max-connections, otherwise can't
    // do anything meaningful here

    if (!max_rps && !conc) {
        log_error(LOG_MISCONFIG, "check-request-limits", sn, rq,
                  XP_GetAdminStr(DBT_reqlimitCantWork));
        return response;
    }

    // Decide bucket name; if none, we use the anonymous bucket anon_bucket

    bucket_info * bucket = NULL;
    const char * bucket_name = pblock_findval(MONITOR_PARAM, pb);
    if (!bucket_name) {
        bucket = &anon_bucket;
    }

    // interval (in seconds), or use default

    int interval = DEFAULT_INTERVAL;
    param = pblock_findval(INTERVAL_PARAM, pb);
    if (param) {
        interval = atoi(param);
    }

    // Check continue, or use default
    int cont = DEFAULT_CONTINUE;
    param = pblock_findval(CONTINUE_PARAM, pb);
    if (param) {
        if (!strcmp(CONT_THRESHOLD_VAL, param)) { cont = CONT_THRESHOLD; }
        else if (!strcmp(CONT_SILENCE_VAL, param)) { cont = CONT_SILENCE; }
        else {
            // Log config error but continue since we have default
            log_error(LOG_MISCONFIG, "check-request-limits", sn, rq,
                      XP_GetAdminStr(DBT_reqlimitBadContinue));
        }
    }

    //----- START_CRIT ------------------------------

    crit_enter(reqlimit_crit);

    if (purge_timeout && (time_now > next_timeout)) { // run purge if needed
        handle_purge_timeout(time_now);
    }

    // If using anon bucket we already have reference to it, otherwise need
    // to go find it in hashtable (and if not found, create one)

    if (!bucket) {

        bucket = (bucket_info *)PL_HashTableLookup(hashtable, bucket_name);

        if (!bucket) {
            // Need to create new entry for this one
            log_error(LOG_VERBOSE, "check-request-limits", sn, rq,
                      "creating new entry for [%s]", bucket_name);
            bucket = (bucket_info *)PERM_MALLOC(sizeof(bucket_info));
            bucket->count = 1;
            bucket->time = time_now + interval;
            bucket->state = REQ_NOACTION;
            bucket->conc = 0;   // handle conc case on initial?
            PL_HashTableAdd(hashtable, 
                            (const void *)PERM_STRDUP(bucket_name), 
                            (void *)bucket);
            // Since it is the first request, no need to check more
            crit_exit(reqlimit_crit);
            return response;
        }
    }

    // If we are doing max-rps limiting then handle it otherwise don't bother

    if (max_rps) {

        bucket->count++;

        if (time_now > bucket->time) { 
            // Interval or more has passed, time to recompute and recheck

            int time_interval = time_now - bucket->time + interval;
            int rps = bucket->count / time_interval;

            log_error(LOG_VERBOSE, "check-request-limits", sn, rq,
                      "bucket [%s] %d req/s (%d req in %d sec)",
                      bucket_name ? bucket_name: "", 
                      rps, bucket->count, time_interval);

            if (rps > max_rps) {
                // Start limiting
                bucket->state = REQ_ABORTED;
                log_error(LOG_WARN,  "check-request-limits", sn, rq,
                          XP_GetAdminStr(DBT_reqlimitAboveMaxRPS),
                          rps, max_rps,
                          bucket_name ? bucket_name: "");

            } else {
                // Reset state if we're under threshhold or if this is first 
                // hit (which means an interval with zero hits has already 
                // passed)
                if ((cont == CONT_THRESHOLD) || (bucket->count == 1)) {
                    bucket->state = REQ_NOACTION;
                }
            }

            // Prepare for next interval by resetting count and recompute time
            bucket->count = 0;
            bucket->time = time_now + interval;
        }

        response = bucket->state;
    }

    // If decision to reject already done, no need to check or increase conc
    // since this is not getting processed anyway. Otherwise, do it if needed.
 
    if (conc && response != REQ_ABORTED) {

        if (bucket->conc >= conc) {
            // Note that this reject is based on conditions at this instant
            // instead of over an interval, so is independent of bucket->state
            response = REQ_ABORTED;

        } else {
            bucket->conc++;
            // This queues up a call to fn associated with req_cleanup
            // (here, reqlimit_conc_done) to be called after request is done
            request_set_data(rq, req_cleanup, bucket);
        }
    }

    crit_exit(reqlimit_crit);

    //----- END_CRIT ------------------------------

    if (response == REQ_NOACTION) {
        return REQ_NOACTION;
    }

    // abort this request

    int err = DEFAULT_ERROR;
    param = pblock_findval(ERROR_PARAM, pb);
    if (param) {
        err = atoi(param);
    }
    protocol_status(sn, rq, err, NULL);

    log_error(LOG_VERBOSE, "check-request-limits", sn, rq,
              "Rejecting request matching bucket [%s] with status %d",
              bucket_name ? bucket_name: "", err);
              
    return response;
}