void add_link_layer_address(unsigned char *ip, unsigned char *link_layer)
{
    uint8_t i, min_time_idx = 0;
    uint32_t min_time;

    min_time = _link_layer_table[0].timestamp;

    for (i = 0 ; i < LINK_LAYER_CACHE_MAX_ENTRY ; ++i)
    {
	if (_link_layer_table[i].timestamp < min_time)
	{
	    min_time = _link_layer_table[i].timestamp;
	    min_time_idx = i;
	}
	if (IP_EQUAL(_link_layer_table[i].ip,ip) || IP_IS_NULL(_link_layer_table[i].ip))
	{
	    memcpy(_link_layer_table[i].link_layer, link_layer, LINK_LAYER_ADDRESS_SIZE);
	    _link_layer_table[i].timestamp = NOW;
	    if (IP_IS_NULL(_link_layer_table[i].ip))
	    {
		COPY_IP(_link_layer_table[i].ip,ip);
	    }
	    return;
	}
    }
    /* every entry is used, remove the oldest one */
    COPY_IP(_link_layer_table[min_time_idx].ip,ip);
    memcpy(_link_layer_table[min_time_idx].link_layer, link_layer, LINK_LAYER_ADDRESS_SIZE);
}
示例#2
0
/*
 * Creates a string ready to write as a token into config or WebIf for an iprange. You must free the returned value through free_mk_t().
 */
char *mk_t_iprange(struct s_ip *range)
{
    struct s_ip *cip;
    char *value, *dot = "";
    int32_t needed = 1, pos = 0;
    for(cip = range; cip; cip = cip->next) {
        needed += 32;
    }

    char tmp[needed];

    for(cip = range; cip; cip = cip->next)
    {
        pos += snprintf(tmp + pos, needed - pos, "%s%s", dot, cs_inet_ntoa(cip->ip[0]));
        if(!IP_EQUAL(cip->ip[0], cip->ip[1]))  {
            pos += snprintf(tmp + pos, needed - pos, "-%s", cs_inet_ntoa(cip->ip[1]));
        }
        dot = ",";
    }
    if(pos == 0 || !cs_malloc(&value, pos + 1)) {
        return "";
    }
    memcpy(value, tmp, pos + 1);
    return value;
}
示例#3
0
/* Resolves the ip of the hostname of the specified account and saves it in account->dynip.
   If the hostname is not configured, the ip is set to 0. */
static void cs_user_resolve(struct s_auth *account)
{
    if (account->dyndns) {
        IN_ADDR_T lastip;
        IP_ASSIGN(lastip, account->dynip);
        cs_resolve(account->dyndns, &account->dynip, NULL, NULL);
        if (!IP_EQUAL(lastip, account->dynip))  {
            cs_log("%s: resolved ip=%s", account->dyndns, cs_inet_ntoa(account->dynip));
        }
    } else {
        set_null_ip(&account->dynip);
    }
}
int get_link_layer_address(const unsigned char *ip, unsigned char *link_layer)
{
    uint8_t i;
    for (i = 0 ; i < LINK_LAYER_CACHE_MAX_ENTRY ; ++i)
    {
		if (IP_EQUAL(_link_layer_table[i].ip,ip))
		{
			memcpy(link_layer, _link_layer_table[i].link_layer, LINK_LAYER_ADDRESS_SIZE);
			return 1;
		}
    }
    return 0;
}
示例#5
0
// if input client is typ proxy get client and vice versa
struct s_client *switch_client_proxy(struct s_client *cli)
{
	struct s_client *cl;
	int8_t typ;
	if(cli->typ == 'c')
		{ typ = 'p'; }
	else
		{ typ = 'c'; }
	for(cl = first_client; cl; cl = cl->next)
	{
		//needfix: only one gbox per IP. Ports?
		if(IP_EQUAL(cli->ip, cl->ip) && cl->typ == typ && cl->gbox)
		{
			return cl;
		}
	}
	return cli;
}
示例#6
0
xkern_return_t
rt_init( XObj self, IPhost *defGw )
{
    PState	*ps = (PState *)self->state;
    RouteTable	*tbl = &ps->rtTbl;
    Path	path = self->path;
    Event	ev;
    
    xTrace0(ipp, TR_GROSS_EVENTS, "IP rt_init()");
    tbl->valid = TRUE;
    tbl->defrt = 0;
    tbl->arr = (route **)pathAlloc(path, ROUTETABLESIZE * sizeof(route *));
    tbl->path = path;
    if ( ! tbl->arr ) {
	xTraceP0(self, TR_ERRORS, "allocation failure");
	return XK_FAILURE;
    }
    bzero((char *)tbl->arr, ROUTETABLESIZE * sizeof(route *));
    tbl->bpoolsize = BPSIZE;
    if ( ! (ev = evAlloc(path)) ) {
	pathFree(tbl->arr);
	xTraceP0(self, TR_ERRORS, "allocation failure");
	return XK_FAILURE;
    }
    if ( IP_EQUAL(*defGw, ipNull) ) {
	xTrace0(ipp, TR_GROSS_EVENTS,
		"IP routing -- default routing disabled");
    } else {
	if ( rt_add_def(ps, defGw) ) {
	    return XK_FAILURE;
	}
    }
    evSchedule(ev, rt_timer, tbl, RTTABLEUPDATE * 1000);
    xTrace0(ipp, TR_GROSS_EVENTS, "IP rt_init() done");
    return XK_SUCCESS;
}
示例#7
0
/**
 * cacheex modes:
 *
 * cacheex=1 CACHE PULL:
 * Situation: oscam A reader1 has cacheex=1, oscam B account1 has cacheex=1
 *   oscam A gets a ECM request, reader1 send this request to oscam B, oscam B checks his cache
 *   a. not found in cache: return NOK
 *   a. found in cache: return OK+CW
 *   b. not found in cache, but found pending request: wait max cacheexwaittime and check again
 *   oscam B never requests new ECMs
 *
 *   CW-flow: B->A
 *
 * cacheex=2 CACHE PUSH:
 * Situation: oscam A reader1 has cacheex=2, oscam B account1 has cacheex=2
 *   if oscam B gets a CW, its pushed to oscam A
 *   reader has normal functionality and can request ECMs
 *
 *   Problem: oscam B can only push if oscam A is connected
 *   Problem or feature?: oscam A reader can request ecms from oscam B
 *
 *   CW-flow: B->A
 *
 */
void cacheex_cache_push(ECM_REQUEST *er)
{
    if(er->rc >= E_NOTFOUND) {
        return;
    }

    //cacheex=2 mode: push (server->remote)
    struct s_client *cl;
    cs_readlock(&clientlist_lock);
    for(cl = first_client->next; cl; cl = cl->next)
    {
        if(check_client(cl) && er->cacheex_src != cl)
        {
            if(get_module(cl)->num == R_CSP)    // always send to csp cl
            {
                if(!er->cacheex_src || cfg.csp.allow_reforward) {
                    cacheex_cache_push_to_client(cl, er);    // but not if the origin was cacheex (might loop)
                }
            }
            else if(cl->typ == 'c' && !cl->dup && cl->account && cl->account->cacheex.mode == 2)      //send cache over user
            {
                if(get_module(cl)->c_cache_push  // cache-push able
                        && (!er->grp || (cl->grp & er->grp)) //Group-check
                        /****  OUTGOING FILTER CHECK ***/
                        && (!er->selected_reader || !cacheex_reader(er->selected_reader) || !cfg.block_same_name || strcmp(username(cl), er->selected_reader->label)) //check reader mode-1 loopback by same name
                        && (!er->selected_reader || !cacheex_reader(er->selected_reader) || !cfg.block_same_ip || (check_client(er->selected_reader->client) && !IP_EQUAL(cl->ip, er->selected_reader->client->ip))) //check reader mode-1 loopback by same ip
                        && (!cl->account->cacheex.drop_csp || checkECMD5(er))  //cacheex_drop_csp-check
                        && chk_ctab(er->caid, &cl->ctab)  					 //Caid-check
                        && (!checkECMD5(er) || chk_ident_filter(er->caid, er->prid, &cl->ftab))	 	 //Ident-check (not for csp: prid=0 always!)
                        && chk_srvid(cl, er) //Service-check
                  )
                {
                    cacheex_cache_push_to_client(cl, er);
                }
            }
        }
    }
    cs_readunlock(&clientlist_lock);


    //cacheex=3 mode: reverse push (reader->server)
    cs_readlock(&readerlist_lock);
    cs_readlock(&clientlist_lock);
    struct s_reader *rdr;
    for(rdr = first_active_reader; rdr; rdr = rdr->next)
    {
        cl = rdr->client;
        if(check_client(cl) && er->cacheex_src != cl && rdr->cacheex.mode == 3)    //send cache over reader
        {
            if(rdr->ph.c_cache_push     // cache-push able
                    && (!er->grp || (rdr->grp & er->grp)) //Group-check
                    /****  OUTGOING FILTER CHECK ***/
                    && (!er->selected_reader || !cacheex_reader(er->selected_reader) || !cfg.block_same_name || strcmp(username(cl), er->selected_reader->label)) //check reader mode-1 loopback by same name
                    && (!er->selected_reader || !cacheex_reader(er->selected_reader) || !cfg.block_same_ip || (check_client(er->selected_reader->client) && !IP_EQUAL(cl->ip, er->selected_reader->client->ip))) //check reader mode-1 loopback by same ip
                    && (!rdr->cacheex.drop_csp || checkECMD5(er))  		 //cacheex_drop_csp-check
                    && chk_ctab(er->caid, &rdr->ctab)  					 //Caid-check
                    && (!checkECMD5(er) || chk_ident_filter(er->caid, er->prid, &rdr->ftab))	 	 //Ident-check (not for csp: prid=0 always!)
                    && chk_srvid(cl, er) //Service-check
              )
            {
                cacheex_cache_push_to_client(cl, er);
            }
        }
    }
    cs_readunlock(&clientlist_lock);
    cs_readunlock(&readerlist_lock);
}
示例#8
0
int32_t cs_auth_client(struct s_client * client, struct s_auth *account, const char *e_txt)
{
    int32_t rc = 0;
    unsigned char md5tmp[MD5_DIGEST_LENGTH];
    char buf[32];
    char *t_crypt = "encrypted";
    char *t_plain = "plain";
    char *t_grant = " granted";
    char *t_reject = " rejected";
    char *t_msg[] = { buf, "invalid access", "invalid ip", "unknown reason", "protocol not allowed" };
    struct s_module *module = get_module(client);

    memset(&client->grp, 0xff, sizeof(uint64_t));
    //client->grp=0xffffffffffffff;
    if ((intptr_t)account != 0 && (intptr_t)account != -1 && account->disabled) {
        cs_add_violation(client, account->usr);
        cs_log("%s %s-client %s%s (%s%sdisabled account)",
               client->crypted ? t_crypt : t_plain,
               module->desc,
               IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "",
               IP_ISSET(client->ip) ? t_reject : t_reject+1,
               e_txt ? e_txt : "",
               e_txt ? " " : "");
        return 1;
    }

    // check whether client comes in over allowed protocol
    if ((intptr_t)account != 0 && (intptr_t)account != -1 && (intptr_t)account->allowedprotocols &&
            (((intptr_t)account->allowedprotocols & module->listenertype) != module->listenertype))
    {
        cs_add_violation(client, account->usr);
        cs_log("%s %s-client %s%s (%s%sprotocol not allowed)",
               client->crypted ? t_crypt : t_plain,
               module->desc,
               IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "",
               IP_ISSET(client->ip) ? t_reject : t_reject+1,
               e_txt ? e_txt : "",
               e_txt ? " " : "");
        return 1;
    }

    client->account = first_client->account;
    switch((intptr_t)account) {

    case 0: { // reject access
        rc = 1;
        cs_add_violation(client, NULL);
        cs_log("%s %s-client %s%s (%s)",
               client->crypted ? t_crypt : t_plain,
               module->desc,
               IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "",
               IP_ISSET(client->ip) ? t_reject : t_reject+1,
               e_txt ? e_txt : t_msg[rc]);
        break;
    }

    default: { // grant/check access
        if (IP_ISSET(client->ip) && account->dyndns) {
            if (!IP_EQUAL(client->ip, account->dynip))
                cs_user_resolve(account);
            if (!IP_EQUAL(client->ip, account->dynip)) {
                cs_add_violation(client, account->usr);
                rc=2;
            }
        }
        client->monlvl = account->monlvl;
        client->account = account;
        if (!rc)
        {
            client->dup=0;
            if (client->typ=='c' || client->typ=='m')
                client->pcrc = crc32(0L, MD5((uchar *)(ESTR(account->pwd)), strlen(ESTR(account->pwd)), md5tmp), MD5_DIGEST_LENGTH);
            if (client->typ=='c')
            {
                client->last_caid = NO_CAID_VALUE;
                client->last_srvid = NO_SRVID_VALUE;
                client->expirationdate = account->expirationdate;
                client->disabled = account->disabled;
                client->allowedtimeframe[0] = account->allowedtimeframe[0];
                client->allowedtimeframe[1] = account->allowedtimeframe[1];
                if (account->firstlogin == 0) account->firstlogin = time((time_t*)0);
                client->failban = account->failban;
                client->c35_suppresscmd08 = account->c35_suppresscmd08;
                client->ncd_keepalive = account->ncd_keepalive;
                client->grp = account->grp;
                client->aureader_list = account->aureader_list;
                client->autoau = account->autoau;
                client->tosleep = (60*account->tosleep);
                client->c35_sleepsend = account->c35_sleepsend;
                memcpy(&client->ctab, &account->ctab, sizeof(client->ctab));
                if (account->uniq)
                    cs_fake_client(client, account->usr, account->uniq, client->ip);
                client->ftab  = account->ftab;   // IDENT filter
                client->cltab = account->cltab;  // CLASS filter
                client->fchid = account->fchid;  // CHID filter
                client->sidtabs.ok= account->sidtabs.ok;   // services
                client->sidtabs.no= account->sidtabs.no;   // services
                memcpy(&client->ttab, &account->ttab, sizeof(client->ttab));
                ac_init_client(client, account);
            }
        }
    }

    case -1: { // anonymous grant access
        if (rc) {
            t_grant = t_reject;
        } else {
            if (client->typ == 'm') {
                snprintf(t_msg[0], sizeof(buf), "lvl=%d", client->monlvl);
            } else {
                int32_t rcount = ll_count(client->aureader_list);
                snprintf(buf, sizeof(buf), "au=");
                if (!rcount)
                    snprintf(buf+3, sizeof(buf)-3, "off");
                else {
                    if (client->autoau)
                        snprintf(buf+3, sizeof(buf)-3, "auto (%d reader)", rcount);
                    else
                        snprintf(buf+3, sizeof(buf)-3, "on (%d reader)", rcount);
                }
            }
        }
        cs_log("%s %s-client %s%s (%s, %s)",
               client->crypted ? t_crypt : t_plain,
               e_txt ? e_txt : module->desc,
               IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "",
               IP_ISSET(client->ip) ? t_grant : t_grant + 1,
               username(client), t_msg[rc]);
        break;
    }
    }
    return rc;
}
示例#9
0
static void cs_fake_client(struct s_client *client, char *usr, int32_t uniq, IN_ADDR_T ip)
{
    /* Uniq = 1: only one connection per user
     *
     * Uniq = 2: set (new connected) user only to fake if source
     *           ip is different (e.g. for newcamd clients with
     *           different CAID's -> Ports)
     *
     * Uniq = 3: only one connection per user, but only the last
     *           login will survive (old mpcs behavior)
     *
     * Uniq = 4: set user only to fake if source ip is
     *           different, but only the last login will survive
     */
    struct s_client *cl;
    struct s_auth *account;
    cs_writelock(&fakeuser_lock);
    for (cl = first_client->next; cl; cl = cl->next)
    {
        account = cl->account;
        if (cl != client && cl->typ == 'c' && !cl->dup && account && streq(account->usr, usr)
                && uniq < 5 && ((uniq % 2) || !IP_EQUAL(cl->ip, ip)))
        {
            char buf[20];
            if (uniq  == 3 || uniq == 4)
            {
                cl->dup = 1;
                cl->aureader_list = NULL;
                cs_strncpy(buf, cs_inet_ntoa(cl->ip), sizeof(buf));
                cs_log("client(%8lX) duplicate user '%s' from %s (prev %s) set to fake (uniq=%d)",
                       (unsigned long)cl->thread, usr, cs_inet_ntoa(ip), buf, uniq);
                if (cl->failban & BAN_DUPLICATE) {
                    cs_add_violation(cl, usr);
                }
                if (cfg.dropdups) {
                    cs_writeunlock(&fakeuser_lock);
                    cs_sleepms(100); // sleep a bit to prevent against saturation from fast reconnecting clients
                    kill_thread(cl);
                    cs_writelock(&fakeuser_lock);
                }
            } else {
                client->dup = 1;
                client->aureader_list = NULL;
                cs_strncpy(buf, cs_inet_ntoa(ip), sizeof(buf));
                cs_log("client(%8lX) duplicate user '%s' from %s (current %s) set to fake (uniq=%d)",
                       (unsigned long)pthread_self(), usr, cs_inet_ntoa(cl->ip), buf, uniq);
                if (client->failban & BAN_DUPLICATE) {
                    cs_add_violation_by_ip(ip, get_module(client)->ptab->ports[client->port_idx].s_port, usr);
                }
                if (cfg.dropdups) {
                    cs_writeunlock(&fakeuser_lock);		// we need to unlock here as cs_disconnect_client kills the current thread!
                    cs_sleepms(100); // sleep a bit to prevent against saturation from fast reconnecting clients
                    cs_disconnect_client(client);
                    cs_writelock(&fakeuser_lock);
                }
                break;
            }
        }
    }
    cs_writeunlock(&fakeuser_lock);
}
示例#10
0
static int32_t cs_check_v(IN_ADDR_T ip, int32_t port, int32_t add, char *info, int32_t acosc_penalty_duration)
{
	int32_t result = 0;
	bool acosc_enabled = false;

#ifdef CS_ANTICASC
	if(cfg.acosc_enabled)
		acosc_enabled = true;
#endif

	if(!(cfg.failbantime || acosc_enabled))
		{ return 0; }

	if(!cfg.v_list)
		{ cfg.v_list = ll_create("v_list"); }

	struct timeb (now);
	cs_ftime(&now);
	LL_ITER itr = ll_iter_create(cfg.v_list);
	V_BAN *v_ban_entry;
	int32_t ftime = cfg.failbantime * 60 * 1000;

	//run over all banned entries to do housekeeping:
	while((v_ban_entry = ll_iter_next(&itr)))
	{
		// housekeeping:
		int32_t gone = comp_timeb(&now, &v_ban_entry->v_time);
		if(((gone >= ftime) && !v_ban_entry->acosc_entry) || (v_ban_entry->acosc_entry && ((gone/1000) >= v_ban_entry->acosc_penalty_dur))) // entry out of time->remove
		{
			NULLFREE(v_ban_entry->info);
			ll_iter_remove_data(&itr);
			continue;
		}

		if(IP_EQUAL(ip, v_ban_entry->v_ip) && port == v_ban_entry->v_port)
		{
			result = 1;
			if(!info)
				{ info = v_ban_entry->info; }
			else if(!v_ban_entry->info)
			{
				v_ban_entry->info = cs_strdup(info);
			}

			if(!add)
			{
				if(v_ban_entry->v_count >= cfg.failbancount)
				{
					if(!v_ban_entry->acosc_entry)
                    	{ cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - %d seconds left%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (ftime - gone)/1000, info ? ", info: " : "", info ? info : ""); }
					else
						{ cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - %d seconds left%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (v_ban_entry->acosc_penalty_dur - (gone/1000)), info?", info: ":"", info?info:""); }

				}
				else
				{
					cs_debug_mask(D_TRACE, "failban: ip %s:%d chance %d of %d%s%s",
								  cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port,
								  v_ban_entry->v_count, cfg.failbancount, info ? ", info: " : "", info ? info : "");
					v_ban_entry->v_count++;
				}
			}
			else
			{
				cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - already exist in list%s%s",
							  cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, info ? ", info: " : "", info ? info : "");
			}
		}
	}

	if(add && !result)
	{
		if(cs_malloc(&v_ban_entry, sizeof(V_BAN)))
		{
			cs_ftime(&v_ban_entry->v_time);
			v_ban_entry->v_ip = ip;
			v_ban_entry->v_port = port;
			v_ban_entry->v_count = 1;
			v_ban_entry->acosc_entry = false;
			v_ban_entry->acosc_penalty_dur = 0;
			if(acosc_penalty_duration > 0)
			{
				v_ban_entry->v_count = cfg.failbancount +1; // set it to a higher level
				v_ban_entry->acosc_entry = true;
				v_ban_entry->acosc_penalty_dur = acosc_penalty_duration;
			}
			if(info)
				{ v_ban_entry->info = cs_strdup(info); }
			ll_iter_insert(&itr, v_ban_entry);
			cs_debug_mask(D_TRACE, "failban: ban ip %s:%d with timestamp %ld%s%s",
						  cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, v_ban_entry->v_time.time,
						  info ? ", info: " : "", info ? info : "");
		}
	}

	return result;
}