source: trunk/oscam-ac.c @ 5375

Last change on this file since 5375 was 5361, checked in by Admin, 8 years ago

Some internal restructuring regarding globals.h file to make it a bit more structured.

File size: 5.2 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2#include "globals.h"
3
4#ifdef CS_ANTICASC
5
6//static time_t ac_last_chk;
7static uchar  ac_ecmd5[CS_ECMSTORESIZE];
8
9int32_t ac_init_log(void)
10{
11  if( (!fpa)  && (cfg.ac_logfile[0]))
12  {
13    if( (fpa=fopen(cfg.ac_logfile, "a+"))<=(FILE *)0 )
14    {
15      fpa=(FILE *)0;
16      fprintf(stderr, "can't open anti-cascading logfile: %s\n", cfg.ac_logfile);
17    }
18    else
19      cs_log("anti-cascading log initialized");
20  }
21
22  return(fpa<=(FILE *)0);
23}
24
25void ac_clear()
26{
27    struct s_client *client;
28    struct s_auth *account;
29   
30    for (client=first_client;client;client=client->next)
31    {
32        if (client->typ != 'c') continue;
33        memset(&client->acasc, 0, sizeof(client->acasc));
34    }
35   
36    for (account=cfg.account;account;account=account->next)
37        memset(&account->ac_stat, 0, sizeof(account->ac_stat));
38}
39
40void ac_done_stat()
41{
42}
43
44void ac_init_stat()
45{
46  ac_clear();
47
48  if( fpa )
49    fclose(fpa);
50  fpa=(FILE *)0;
51  if( ac_init_log() )
52    cs_exit(0);
53}
54
55void ac_do_stat()
56{
57  int32_t j, idx, exceeds, maxval, prev_deny=0;
58
59  struct s_client *client;
60  for (client=first_client;client;client=client->next)
61  {
62    if (client->typ != 'c') continue;
63   
64    struct s_acasc *ac_stat = &client->account->ac_stat;
65    struct s_acasc_shm *acasc = &client->acasc;
66
67    idx = ac_stat->idx;
68    ac_stat->stat[idx] = acasc->ac_count;
69    acasc->ac_count=0;
70
71    if( ac_stat->stat[idx])
72    {
73      if( client->account->ac_penalty==2 ) {// banned
74        cs_debug_mask(D_CLIENT, "user '%s' banned", client->account->usr);
75        acasc->ac_deny=1;
76      }
77      else
78      {
79        for(j=exceeds=maxval=0; j<cfg.ac_samples; j++) 
80        {
81          if (ac_stat->stat[j] > maxval)
82            maxval=ac_stat->stat[j];
83          exceeds+=(ac_stat->stat[j] > client->ac_limit);
84        }
85        prev_deny=acasc->ac_deny;
86        acasc->ac_deny = (exceeds >= cfg.ac_denysamples);
87       
88        cs_debug_mask(D_CLIENT, "%s limit=%d, max=%d, samples=%d, dsamples=%d, [idx=%d]:",
89          client->account->usr, client->ac_limit, maxval, 
90          cfg.ac_samples, cfg.ac_denysamples, idx);
91        cs_debug_mask(D_CLIENT, "%d %d %d %d %d %d %d %d %d %d ", ac_stat->stat[0],
92          ac_stat->stat[1], ac_stat->stat[2], ac_stat->stat[3],
93          ac_stat->stat[4], ac_stat->stat[5], ac_stat->stat[6],
94          ac_stat->stat[7], ac_stat->stat[8], ac_stat->stat[9]);
95        if( acasc->ac_deny ) {
96          cs_log("user '%s' exceeds limit", client->account->usr);
97          ac_stat->stat[idx] = 0;
98        } else if( prev_deny )
99          cs_log("user '%s' restored access", client->account->usr);
100      }
101    }
102    else if (acasc->ac_deny)
103    {
104      prev_deny=1;
105      acasc->ac_deny=0;
106      cs_log("restored access for inactive user '%s'", client->account->usr);
107    }
108
109    if (!acasc->ac_deny && !prev_deny)
110      ac_stat->idx = (ac_stat->idx + 1) % cfg.ac_samples;
111  }
112}
113
114/* Starts the anticascader thread. */
115void start_anticascader(){
116  struct s_client * cl = create_client(first_client->ip);
117  if (cl == NULL) return;
118  cl->thread = pthread_self();
119  pthread_setspecific(getclient, cl);
120  cl->typ = 'a';
121
122  ac_init_stat();
123  while(1)
124  {
125    int32_t i;
126    for( i=0; i<cfg.ac_stime*60; i++ )
127        cs_sleepms(1000); //FIXME this is a cpu-killer!
128    ac_do_stat();
129  }
130}
131
132void ac_init_client(struct s_client *client, struct s_auth *account)
133{
134  client->ac_limit = 0;
135  if( cfg.ac_enabled )
136  {
137    if( account->ac_users )
138    {
139      client->ac_limit = (account->ac_users*100+80)*cfg.ac_stime;
140      cs_debug_mask(D_CLIENT, "login '%s', users=%d, stime=%d min, dwlimit=%d per min, penalty=%d", 
141              account->usr, account->ac_users, cfg.ac_stime, 
142              account->ac_users*100+80, account->ac_penalty);
143    }
144    else
145    {
146      cs_debug_mask(D_CLIENT, "anti-cascading not used for login '%s'", account->usr);
147    }
148  }
149}
150
151static int32_t ac_dw_weight(ECM_REQUEST *er)
152{
153  struct s_cpmap *cpmap;
154
155  for( cpmap=cfg.cpmap; (cpmap) ; cpmap=cpmap->next )
156    if( (cpmap->caid  ==0 || cpmap->caid  ==er->caid)  &&
157        (cpmap->provid==0 || cpmap->provid==er->prid)  &&
158        (cpmap->sid   ==0 || cpmap->sid   ==er->srvid) &&
159        (cpmap->chid  ==0 || cpmap->chid  ==er->chid) )
160      return (cpmap->dwtime*100/60);
161
162  cs_debug_mask(D_CLIENT, "WARNING: CAID %04X, PROVID %06X, SID %04X, CHID %04X not found in oscam.ac", 
163           er->caid, er->prid, er->srvid, er->chid);
164  cs_debug_mask(D_CLIENT, "set DW lifetime 10 sec");
165  return 16; // 10*100/60
166}
167
168void ac_chk(struct s_client *cl, ECM_REQUEST *er, int32_t level)
169{
170    if (!cl->ac_limit || !cfg.ac_enabled) return;
171
172    struct s_acasc_shm *acasc = &cl->acasc;
173
174    if( level == 1 ) {
175        if( er->rc == E_FAKE )
176            acasc->ac_count++;
177
178        if( er->rc >= E_NOTFOUND )
179            return; // not found
180
181        if( memcmp(ac_ecmd5, er->ecmd5, CS_ECMSTORESIZE) != 0 ) {
182            acasc->ac_count += ac_dw_weight(er);
183            memcpy(ac_ecmd5, er->ecmd5, CS_ECMSTORESIZE);
184        }
185        return;
186    }
187
188    if( acasc->ac_deny ) {
189        if( cl->account->ac_penalty ) {
190            if (cl->account->ac_penalty == 3) {
191                cs_debug_mask(D_CLIENT, "fake delay %dms", cfg.ac_fakedelay);
192            } else {
193                cs_debug_mask(D_CLIENT, "send fake dw");
194                er->rc = E_FAKE; // fake
195                er->rcEx = 0;
196            }
197            cs_sleepms(cfg.ac_fakedelay);
198        }
199    }
200}
201#endif
Note: See TracBrowser for help on using the repository browser.