source: trunk/oscam-ac.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

File size: 4.7 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];
8struct s_acasc ac_stat[CS_MAXPID];
9
10int ac_init_log(char *file)
11{
12 if( (!fpa) && (file[0]))
13 {
14 if( (fpa=fopen(file, "a+"))<=(FILE *)0 )
15 {
16 fpa=(FILE *)0;
17 fprintf(stderr, "can't open anti-cascading logfile: %s\n", file);
18 }
19 else
20 cs_log("anti-cascading log initialized");
21 }
22
23 return(fpa<=(FILE *)0);
24}
25
26void ac_init_stat()
27{
28 memset(ac_stat, 0, sizeof(ac_stat));
29 memset(acasc, 0, sizeof(acasc));
30
31 if( fpa )
32 fclose(fpa);
33 fpa=(FILE *)0;
34 if( ac_init_log(cfg->ac_logfile) )
35 cs_exit(0);
36}
37
38int idx_from_ac_idx(int ac_idx)
39{
40 int i;
41
42 for( i=0; i<CS_MAXPID; i++ )
43 if( client[i].ac_idx==ac_idx ) return i;
44
45 return -1;
46}
47
48void ac_do_stat()
49{
50 int i, j, idx, exceeds, maxval, prev_deny=0;
51 int cl_idx;
52
53 for( i=0; i<CS_MAXPID; i++ )
54 {
55 idx = ac_stat[i].idx;
56 ac_stat[i].stat[idx] = acasc[i].ac_count;
57 acasc[i].ac_count=0;
58 cl_idx = idx_from_ac_idx(i);
59
60 if( ac_stat[i].stat[idx] )
61 {
62 if( cl_idx==-1 ) {
63 cs_log("ERROR: can't find client with ac_idx=%d", i);
64 continue;
65 }
66
67 if( client[cl_idx].ac_penalty==2 ) {// banned
68 cs_debug("user '%s' banned", client[cl_idx].usr);
69 acasc[i].ac_deny=1;
70 }
71 else
72 {
73 for( j=exceeds=maxval=0; j<cfg->ac_samples; j++ )
74 {
75 if( ac_stat[i].stat[j] > maxval )
76 maxval=ac_stat[i].stat[j];
77 exceeds+=(ac_stat[i].stat[j]>client[cl_idx].ac_limit);
78 }
79 prev_deny=acasc[i].ac_deny;
80 acasc[i].ac_deny = (exceeds >= cfg->ac_denysamples);
81
82 cs_debug("%s limit=%d, max=%d, samples=%d, dsamples=%d, ac[ci=%d][si=%d]:",
83 client[cl_idx].usr, client[cl_idx].ac_limit, maxval,
84 cfg->ac_samples, cfg->ac_denysamples, i, idx);
85 cs_debug("%d %d %d %d %d %d %d %d %d %d ", ac_stat[i].stat[0],
86 ac_stat[i].stat[1], ac_stat[i].stat[2], ac_stat[i].stat[3],
87 ac_stat[i].stat[4], ac_stat[i].stat[5], ac_stat[i].stat[6],
88 ac_stat[i].stat[7], ac_stat[i].stat[8], ac_stat[i].stat[9]);
89 if( acasc[i].ac_deny ) {
90 cs_log("user '%s' exceeds limit", client[cl_idx].usr);
91 ac_stat[i].stat[idx] = 0;
92 } else if( prev_deny )
93 cs_log("user '%s' restored access", client[cl_idx].usr);
94 }
95 }
96 else if( acasc[i].ac_deny )
97 {
98 prev_deny=1;
99 acasc[i].ac_deny=0;
100 if( cl_idx!=-1 )
101 cs_log("restored access for inactive user '%s'", client[cl_idx].usr);
102 else
103 cs_log("restored access for unknown user (ac_idx=%d)", i);
104 }
105
106 if( !acasc[i].ac_deny && !prev_deny )
107 ac_stat[i].idx = (ac_stat[i].idx + 1) % cfg->ac_samples;
108 }
109}
110
111void ac_init_client(struct s_auth *account)
112{
113 client[cs_idx].ac_idx = account->ac_idx;
114 client[cs_idx].ac_limit = 0;
115 if( cfg->ac_enabled )
116 {
117 if( account->ac_users )
118 {
119 client[cs_idx].ac_limit = (account->ac_users*100+80)*cfg->ac_stime;
120 client[cs_idx].ac_penalty = account->ac_penalty;
121 cs_debug("login '%s', ac_idx=%d, users=%d, stime=%d min, dwlimit=%d per min, penalty=%d",
122 account->usr, account->ac_idx, account->ac_users, cfg->ac_stime,
123 account->ac_users*100+80, account->ac_penalty);
124 }
125 else
126 cs_debug("anti-cascading not used for login '%s'", account->usr);
127 }
128}
129
130static int ac_dw_weight(ECM_REQUEST *er)
131{
132 struct s_cpmap *cpmap;
133
134 for( cpmap=cfg->cpmap; (cpmap) ; cpmap=cpmap->next )
135 if( (cpmap->caid ==0 || cpmap->caid ==er->caid) &&
136 (cpmap->provid==0 || cpmap->provid==er->prid) &&
137 (cpmap->sid ==0 || cpmap->sid ==er->srvid) &&
138 (cpmap->chid ==0 || cpmap->chid ==er->chid) )
139 return (cpmap->dwtime*100/60);
140
141 cs_debug("WARNING: CAID %04X, PROVID %06X, SID %04X, CHID %04X not found in oscam.ac",
142 er->caid, er->prid, er->srvid, er->chid);
143 cs_debug("set DW lifetime 10 sec");
144 return 16; // 10*100/60
145}
146
147void ac_chk(ECM_REQUEST *er, int level)
148{
149 if( !client[cs_idx].ac_limit || !cfg->ac_enabled ) return;
150
151 if( level==1 )
152 {
153 if( er->rc==7 ) acasc[client[cs_idx].ac_idx].ac_count++;
154 if( er->rc>3 ) return; // not found
155 if( memcmp(ac_ecmd5, er->ecmd5, CS_ECMSTORESIZE) != 0 )
156 {
157 acasc[client[cs_idx].ac_idx].ac_count+=ac_dw_weight(er);
158 memcpy(ac_ecmd5, er->ecmd5, CS_ECMSTORESIZE);
159 }
160 return;
161 }
162
163 if( acasc[client[cs_idx].ac_idx].ac_deny )
164 if( client[cs_idx].ac_penalty )
165 {
166 cs_debug("send fake dw");
167 er->rc=7; // fake
168 er->rcEx=0;
169 cs_sleepms(cfg->ac_fakedelay);
170 }
171}
172#endif
Note: See TracBrowser for help on using the repository browser.