예제 #1
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;
}
예제 #2
0
/* Calculates a new opaque value. Please note that opaque needs to be at least (MD5_DIGEST_LENGTH * 2) + 1 large. */
void calculate_opaque(IN_ADDR_T addr, char *opaque)
{
	char noncetmp[128];
	unsigned char md5tmp[MD5_DIGEST_LENGTH];
	snprintf(noncetmp, sizeof(noncetmp), "%d:%s:%d", (int32_t)time(NULL), cs_inet_ntoa(addr), (int16_t)rand());
	char_to_hex(MD5((unsigned char *)noncetmp, strlen(noncetmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)opaque);
}
예제 #3
0
static void radegast_server_init(struct s_client *cl) {
	if (!cl->init_done) {
		if (IP_ISSET(cl->ip))
			cs_log("radegast: new connection from %s", cs_inet_ntoa(cl->ip));
		radegast_auth_client(cur_client()->ip);
		cl->init_done=1;
	}
	return;
}
예제 #4
0
void cs_disconnect_client(struct s_client * client)
{
    char buf[32] = { 0 };
    if (IP_ISSET(client->ip))
        snprintf(buf, sizeof(buf), " from %s", cs_inet_ntoa(client->ip));
    cs_log("%s disconnected%s", username(client), buf);
    if (client == cur_client())
        cs_exit(0);
    else
        kill_thread(client);
}
예제 #5
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);
    }
}
예제 #6
0
static void serverip_fn(const char *token, char *value, void *setting, FILE *f) {
	IN_ADDR_T srvip = *(IN_ADDR_T *)setting;
	if (value) {
		if (strlen(value) == 0) {
			set_null_ip((IN_ADDR_T *)setting);
		} else {
			cs_inet_addr(value, (IN_ADDR_T *)setting);
		}
		return;
	}
	if (IP_ISSET(srvip) || cfg.http_full_cfg)
		fprintf_conf(f, token, "%s\n", cs_inet_ntoa(srvip));
}
예제 #7
0
void gbox_write_peer_onl(void)
{
	FILE *fhandle = fopen(FILE_GBOX_PEER_ONL, "w");
	if(!fhandle)
	{
		cs_log("Couldn't open %s: %s\n", FILE_GBOX_PEER_ONL, strerror(errno));
		return;
	}
	struct s_client *cl;
	for(cl = first_client; cl; cl = cl->next)
	{
		if(cl->gbox && (cl->typ == 'p'))
		{
			struct gbox_peer *peer = cl->gbox;
			if (peer->online)
				{ fprintf(fhandle, "1 %s  %s %04X 2.%02X\n",cl->reader->device, cs_inet_ntoa(cl->ip),peer->gbox.id, peer->gbox.minor_version); }
			else
				{ fprintf(fhandle, "0 %s  %s %04X 0.00\n",cl->reader->device, cs_inet_ntoa(cl->ip),peer->gbox.id); }
		}
	}
	fclose(fhandle);
	return;
}	
예제 #8
0
static void gbox_server_init(struct s_client *cl)
{
	if(!cl->init_done)
	{
		if(IP_ISSET(cl->ip))
			{ cs_log("gbox: new connection from %s", cs_inet_ntoa(cl->ip)); }
		gbox_auth_client(cl);
		if(cl->gbox)
		{
			gbox_local_cards(cl);
			cl->init_done = 1;
		}
	}
	return;
}
예제 #9
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;
}
예제 #10
0
struct s_client *create_client(IN_ADDR_T ip) {
    struct s_client *cl;
    if (!cs_malloc(&cl, sizeof(struct s_client))) {
        cs_log("max connections reached (out of memory) -> reject client %s", IP_ISSET(ip) ? cs_inet_ntoa(ip) : "with null address");
        return NULL;
    }
    //client part
    IP_ASSIGN(cl->ip, ip);
    cl->account = first_client->account;
    //master part
    pthread_mutex_init(&cl->thread_lock, NULL);
    cl->login = cl->last = time(NULL);
    cl->tid = (uint32_t)(uintptr_t)cl;	// Use pointer adress of client as threadid (for monitor and log)
    //Now add new client to the list:
    struct s_client *last;
    cs_writelock(&clientlist_lock);
    if (sizeof(uintptr_t) > 4) {		// 64bit systems can have collisions because of the cast so lets check if there are some
        int8_t found;
        do {
            found = 0;
            for (last=first_client; last; last=last->next) {
                if (last->tid == cl->tid) {
                    found = 1;
                    break;
                }
            }
            if (found || cl->tid == 0) {
                cl->tid = (uint32_t)rand();
            }
        } while (found || cl->tid == 0);
    }
    for (last = first_client; last->next != NULL; last = last->next)
        ; //ends with cl on last client
    last->next = cl;
    int32_t bucket = (uintptr_t)cl/16 % CS_CLIENT_HASHBUCKETS;
    cl->nexthashed = first_client_hashed[bucket];
    first_client_hashed[bucket] = cl;
    cs_writeunlock(&clientlist_lock);
    return cl;
}
예제 #11
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);
}
예제 #12
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;
}
예제 #13
0
/* Checks if authentication is correct. Returns -1 if not correct, 1 if correct and 2 if nonce isn't valid anymore.
   Note that authstring will be modified. */
int32_t check_auth(char *authstring, char *method, char *path, IN_ADDR_T addr, char *expectednonce, char *opaque)
{
	int32_t authok = 0, uriok = 0;
	char authnonce[(MD5_DIGEST_LENGTH * 2) + 1];
	memset(authnonce, 0, sizeof(authnonce));
	char *authnc = "";
	char *authcnonce = "";
	char *authresponse = "";
	char *uri = "";
	char *username = "";
	char *expectedPassword = cfg.http_pwd;
	char *pch = authstring + 22;
	char *pch2;
	char *saveptr1 = NULL;
	memset(opaque, 0, (MD5_DIGEST_LENGTH * 2) + 1);

	for(pch = strtok_r(pch, ",", &saveptr1); pch; pch = strtok_r(NULL, ",", &saveptr1))
	{
		pch2 = pch;
		while(pch2[0] == ' ' && pch2[0] != '\0') { ++pch2; }
		if(strncmp(pch2, "nonce", 5) == 0)
		{
			cs_strncpy(authnonce, parse_auth_value(pch2), sizeof(authnonce));
		}
		else if(strncmp(pch2, "nc", 2) == 0)
		{
			authnc = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "cnonce", 6) == 0)
		{
			authcnonce = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "response", 8) == 0)
		{
			authresponse = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "uri", 3) == 0)
		{
			uri = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "username", 8) == 0)
		{
			username = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "opaque", 6) == 0)
		{
			char *tmp = parse_auth_value(pch2);
			cs_strncpy(opaque, tmp, (MD5_DIGEST_LENGTH * 2) + 1);
		}
	}

	if(strncmp(uri, path, strlen(path)) == 0) { uriok = 1; }
	else
	{
		pch2 = uri;
		for(pch = uri; pch[0] != '\0'; ++pch)
		{
			if(pch[0] == '/') { pch2 = pch; }
			if(strncmp(pch2, path, strlen(path)) == 0) { uriok = 1; }
		}
	}
	if(uriok == 1 && streq(username, cfg.http_user))
	{
		char A1tmp[3 + strlen(username) + strlen(AUTHREALM) + strlen(expectedPassword)];
		char A1[(MD5_DIGEST_LENGTH * 2) + 1], A2[(MD5_DIGEST_LENGTH * 2) + 1], A3[(MD5_DIGEST_LENGTH * 2) + 1];
		unsigned char md5tmp[MD5_DIGEST_LENGTH];
		snprintf(A1tmp, sizeof(A1tmp), "%s:%s:%s", username, AUTHREALM, expectedPassword);
		char_to_hex(MD5((unsigned char *)A1tmp, strlen(A1tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A1);

		char A2tmp[2 + strlen(method) + strlen(uri)];
		snprintf(A2tmp, sizeof(A2tmp), "%s:%s", method, uri);
		char_to_hex(MD5((unsigned char *)A2tmp, strlen(A2tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A2);

		char A3tmp[10 + strlen(A1) + strlen(A2) + strlen(authnonce) + strlen(authnc) + strlen(authcnonce)];
		snprintf(A3tmp, sizeof(A3tmp), "%s:%s:%s:%s:auth:%s", A1, authnonce, authnc, authcnonce, A2);
		char_to_hex(MD5((unsigned char *)A3tmp, strlen(A3tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A3);

		if(strcmp(A3, authresponse) == 0)
		{
			if(strlen(opaque) != MD5_DIGEST_LENGTH * 2) { calculate_opaque(addr, opaque); }
			calculate_nonce(authnonce, expectednonce, opaque);
			if(strcmp(expectednonce, authnonce) == 0) { authok = 1; }
			else
			{
				authok = 2;
				cs_debug_mask(D_TRACE, "WebIf: Received stale header from %s (nonce=%s, expectednonce=%s, opaque=%s).", cs_inet_ntoa(addr), authnonce, expectednonce, opaque);
			}
		}
	}
	return authok;
}
예제 #14
0
void add_cache(ECM_REQUEST *er){
	if(!er->csp_hash) return;

	ECMHASH *result = NULL;
	CW *cw = NULL;
#ifdef CS_CACHEEX
	bool add_new_cw=false;
#endif

	pthread_rwlock_wrlock(&cache_lock);

	//add csp_hash to cache
	result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t), &compare_csp_hash);
	if(!result){
		if(cs_malloc(&result, sizeof(ECMHASH))){
			result->csp_hash = er->csp_hash;
			init_hash_table(&result->ht_cw, &result->ll_cw);
			cs_ftime(&result->first_recv_time);

			add_hash_table(&ht_cache, &result->ht_node, &ll_cache, &result->ll_node, result, &result->csp_hash, sizeof(int32_t));

		}else{
			pthread_rwlock_unlock(&cache_lock);
			cs_log("ERROR: NO added HASH to cache!!");
			return;
		}
	}

	cs_ftime(&result->upd_time);   //need to be updated at each cw! We use it for deleting this hash when no more cws arrive inside max_cache_time!


	//add cw to this csp hash
	cw = find_hash_table(&result->ht_cw, er->cw, sizeof(er->cw), &compare_cw);

	if(!cw){

		if(count_hash_table(&result->ht_cw)>=10){  //max 10 different cws stored
			pthread_rwlock_unlock(&cache_lock);
			return;
		}

		while(1){
			if(cs_malloc(&cw, sizeof(CW))){
				memcpy(cw->cw, er->cw, sizeof(er->cw));
				cw->odd_even = get_odd_even(er);
				cw->cwc_cycletime = er->cwc_cycletime;
				cw->cwc_next_cw_cycle = er->cwc_next_cw_cycle;
				cw->count= 0;
				cw->csp = 0;
				cw->cacheex = 0;
				cw->localcards=0;
				cw->proxy=0;
				cw->grp = 0;
				cw->caid = er->caid;
				cw->prid = er->prid;
				cw->srvid = er->srvid;
				cw->selected_reader=er->selected_reader;
	#ifdef CS_CACHEEX
				cw->cacheex_src=er->cacheex_src;
	#endif
				cw->pushout_client = NULL;

				while(1){
					if (pthread_rwlock_init(&cw->pushout_client_lock, NULL) == 0)
						break;

					cs_log("Error creating lock pushout_client_lock!");
					cs_sleepms(1);
				}


				add_hash_table(&result->ht_cw, &cw->ht_node, &result->ll_cw, &cw->ll_node, cw, cw->cw, sizeof(er->cw));

	#ifdef CS_CACHEEX
				add_new_cw=true;
	#endif
				break;
			}

			cs_log("ERROR: NO added CW to cache!! Re-trying...");
			cs_sleepms(1);
		}
	}

	//update if answered from csp/cacheex/local_proxy
	if(er->from_cacheex) cw->cacheex = 1;
	if(er->from_csp) cw->csp = 1;
#ifdef CS_CACHEEX
	if(!er->cacheex_src){
#endif
		if(is_localreader(er->selected_reader, er)) cw->localcards=1;
		else cw->proxy = 1;
#ifdef CS_CACHEEX
	}
#endif

	//always update group and counter
	cw->grp |= er->grp;
	cw->count++;

	//sort cw_list by counter (DESC order)
	if(cw->count>1)
		sort_list(&result->ll_cw, count_sort);

	pthread_rwlock_unlock(&cache_lock);


#ifdef CS_CACHEEX

	er->cw_cache=cw;
	cacheex_cache_push(er);


	//cacheex debug log lines and cw diff stuff
	if(check_client(er->cacheex_src)){
		if(add_new_cw){
			debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src));

			CW *cw_first = get_first_cw(result, er);

			if(er && cw_first){
			
			//compare er cw with mostly counted cached cw
			if(memcmp(er->cw, cw_first->cw, sizeof(er->cw)) != 0) {
				er->cacheex_src->cwcacheexerrcw++;
				if (er->cacheex_src->account)
					er->cacheex_src->account->cwcacheexerrcw++;

				if (((0x0200| 0x0800) & cs_dblevel)) { //avoid useless operations if debug is not enabled
					char cw1[16*3+2], cw2[16*3+2];
					cs_hexdump(0, er->cw, 16, cw1, sizeof(cw1));
					cs_hexdump(0, cw_first->cw, 16, cw2, sizeof(cw2));

					char ip1[20]="", ip2[20]="";
					if (check_client(er->cacheex_src))
						cs_strncpy(ip1, cs_inet_ntoa(er->cacheex_src->ip), sizeof(ip1));
					if (check_client(cw_first->cacheex_src))
						cs_strncpy(ip2, cs_inet_ntoa(cw_first->cacheex_src->ip), sizeof(ip2));
					else if (cw_first->selected_reader && check_client(cw_first->selected_reader->client))
						cs_strncpy(ip2, cs_inet_ntoa(cw_first->selected_reader->client->ip), sizeof(ip2));

					debug_ecm(D_CACHEEX| D_CSP, "WARNING: Different CWs %s from %s(%s)<>%s(%s): %s<>%s ", buf,
						er->from_csp ? "csp" : username(er->cacheex_src), ip1,
						check_client(cw_first->cacheex_src)?username(cw_first->cacheex_src):(cw_first->selected_reader?cw_first->selected_reader->label:"unknown/csp"), ip2,
						cw1, cw2);
				}
			}

		}
		}else
			debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src));
	}

#endif
}
예제 #15
0
void cs_statistics(struct s_client *client)
{
	if(!cfg.disableuserfile)
	{
		struct tm lt;
		char buf[LOG_BUF_SIZE];

		float cwps;

		time_t walltime = cs_time();
		localtime_r(&walltime, &lt);
		if(client->cwfound + client->cwnot > 0)
		{
			cwps = client->last - client->login;
			cwps /= client->cwfound + client->cwnot;
		}
		else
			{ cwps = 0; }

		char channame[CS_SERVICENAME_SIZE];
		get_servicename(client, client->last_srvid, client->last_provid, client->last_caid, channame, sizeof(channame));

		int32_t lsec;
		if((client->last_caid == NO_CAID_VALUE) && (client->last_srvid == NO_SRVID_VALUE))
			{ lsec = client->last - client->login; } //client leave calc total duration
		else
			{ lsec = client->last - client->lastswitch; }

		int32_t secs = 0, fullmins = 0, mins = 0, fullhours = 0;

		if((lsec > 0) && (lsec < 1000000))
		{
			secs = lsec % 60;
			if(lsec > 60)
			{
				fullmins = lsec / 60;
				mins = fullmins % 60;
				if(fullmins > 60)
				{
					fullhours = fullmins / 60;
				}
			}
		}

		/* statistics entry start with 's' to filter it out on other end of pipe
		 * so we can use the same Pipe as Log
		 */
		snprintf(buf, sizeof(buf), "s%02d.%02d.%02d %02d:%02d:%02d %3.1f %s %s %d %d %d %d %d %d %d %ld %ld %02d:%02d:%02d %s %04X@%06X:%04X %s\n",
				 lt.tm_mday, lt.tm_mon + 1, lt.tm_year % 100,
				 lt.tm_hour, lt.tm_min, lt.tm_sec, cwps,
				 client->account->usr,
				 cs_inet_ntoa(client->ip),
				 client->port,
				 client->cwfound,
				 client->cwcache,
				 client->cwnot,
				 client->cwignored,
				 client->cwtout,
				 client->cwtun,
				 client->login,
				 client->last,
				 fullhours, mins, secs,
				 get_module(client)->desc,
				 client->last_caid,
				 client->last_provid,
				 client->last_srvid,
				 channame);

		cs_write_log_int(buf);
	}
}
예제 #16
0
static char *monitor_client_info(char id, struct s_client *cl, char *sbuf){
	char channame[32];
	sbuf[0] = '\0';

	if (cl){
		char ldate[16], ltime[16], *usr;
		int32_t lsec, isec, con, cau, lrt =- 1;
		time_t now;
		struct tm lt;
		now=time((time_t*)0);

		if	((cfg.hideclient_to <= 0) ||
				(now-cl->lastecm < cfg.hideclient_to) ||
				(now-cl->lastemm < cfg.hideclient_to) ||
				(cl->typ != 'c'))
		{
			lsec = now - cl->login;
			isec = now - cl->last;
			usr = username(cl);
			if (cl->dup)
				con = 2;
			else
				if ((cl->tosleep) && (now-cl->lastswitch>cl->tosleep))
					con = 1;
				else
					con = 0;

			// no AU reader == 0 / AU ok == 1 / Last EMM > aulow == -1
			if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r') {

				if ((cl->typ == 'c' && ll_count(cl->aureader_list) == 0) ||
						((cl->typ == 'p' || cl->typ == 'r') && cl->reader->audisabled))
					cau = 0;

				else if ((now-cl->lastemm) / 60 > cfg.aulow)
					cau = (-1);

				else
					cau = 1;

			} else {
				cau = 0;
			}

			if( cl->typ == 'r')
			{
				int32_t i;
				struct s_reader *rdr;
				for (i=0,rdr=first_active_reader; rdr ; rdr=rdr->next, i++)
					if (cl->reader == rdr)
						lrt=i;

				if( lrt >= 0 )
					lrt = 10 + cl->reader->card_status;
			}
			else
                lrt = cl->cwlastresptime;
			localtime_r(&cl->login, &lt);
			snprintf(ldate, sizeof(ldate), "%02d.%02d.%02d", lt.tm_mday, lt.tm_mon+1, lt.tm_year % 100);
			int32_t cnr=get_threadnum(cl);
			snprintf(ltime, sizeof(ldate), "%02d:%02d:%02d", lt.tm_hour, lt.tm_min, lt.tm_sec);
			snprintf(sbuf, 256, "[%c--CCC]%8X|%c|%d|%s|%d|%d|%s|%d|%s|%s|%s|%d|%04X:%04X|%s|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d\n",
					id, cl->tid, cl->typ, cnr, usr, cau, cl->crypted,
					cs_inet_ntoa(cl->ip), cl->port, client_get_proto(cl),
					ldate, ltime, lsec, cl->last_caid, cl->last_srvid,
					get_servicename(cl, cl->last_srvid, cl->last_caid, channame), isec, con,
                                        cl->cwfound, cl->cwnot, cl->cwcache, cl->cwignored,
                                        cl->cwtout, cl->emmok, cl->emmnok, lrt);
		}
	}
	return sbuf;
}
예제 #17
0
void cs_statistics(struct s_client * client)
{
	if (!cfg.disableuserfile){
		time_t t;
		struct tm lt;
		char buf[LOG_BUF_SIZE];

		float cwps;

		time(&t);
		localtime_r(&t, &lt);
		if (client->cwfound+client->cwnot>0)
		{
			cwps=client->last-client->login;
			cwps/=client->cwfound+client->cwnot;
		}
		else
			cwps=0;

		char channame[32];
		if(cfg.mon_appendchaninfo)
			get_servicename(client, client->last_srvid,client->last_caid, channame);
		else
			channame[0] = '\0';

		int32_t lsec;
		if ((client->last_caid == 0xFFFF) && (client->last_srvid == 0xFFFF))
			lsec = client->last - client->login; //client leave calc total duration
		else
			lsec = client->last - client->lastswitch;

		int32_t secs = 0, fullmins = 0, mins = 0, fullhours = 0;

		if((lsec > 0) && (lsec < 1000000)) {
			secs = lsec % 60;
			if (lsec > 60) {
				fullmins = lsec / 60;
				mins = fullmins % 60;
				if(fullmins > 60) {
					fullhours = fullmins / 60;
				}
			}
		}

		/* statistics entry start with 's' to filter it out on other end of pipe
		 * so we can use the same Pipe as Log
		 */
		snprintf(buf, sizeof(buf), "s%02d.%02d.%02d %02d:%02d:%02d %3.1f %s %s %d %d %d %d %d %d %d %ld %ld %02d:%02d:%02d %s %04X:%04X %s\n",
				lt.tm_mday, lt.tm_mon+1, lt.tm_year%100,
				lt.tm_hour, lt.tm_min, lt.tm_sec, cwps,
				client->account->usr,
				cs_inet_ntoa(client->ip),
				client->port,
				client->cwfound,
				client->cwcache,
				client->cwnot,
				client->cwignored,
				client->cwtout,
				client->cwtun,
				client->login,
				client->last,
				fullhours, mins, secs,
				ph[client->ctyp].desc,
				client->last_caid,
				client->last_srvid,
				channame);

		cs_write_log_int(buf);
	}
}
예제 #18
0
파일: oscam-client.c 프로젝트: FFTEAM/oscam
struct s_client *create_client(IN_ADDR_T ip)
{
	struct s_client *cl;
	if(!cs_malloc(&cl, sizeof(struct s_client)))
	{
		cs_log("max connections reached (out of memory) -> reject client %s", IP_ISSET(ip) ? cs_inet_ntoa(ip) : "with null address");
		return NULL;
	}
	
	//client part
	IP_ASSIGN(cl->ip, ip);
	cl->account = first_client->account;
	
	//master part
	SAFE_MUTEX_INIT(&cl->thread_lock, NULL);
	cl->login = cl->last = time(NULL);
	cl->tid = (uint32_t)rand();
	
	//Now add new client to the list:
	struct s_client *last;
	cs_writelock(__func__, &clientlist_lock);
	
	for(last = first_client; last && last->next; last = last->next)
		{ ; } //ends with cl on last client
		
	if (last)
		last->next = cl;
		
	int32_t bucket = (uintptr_t)cl / 16 % CS_CLIENT_HASHBUCKETS;
	cl->nexthashed = first_client_hashed[bucket];
	first_client_hashed[bucket] = cl;
	
	cs_writeunlock(__func__, &clientlist_lock);
	
	return cl;
}