source: trunk/oscam-ac.c@ 4149

Last change on this file since 4149 was 4141, checked in by dingo35, 13 years ago

all: simplify debug system, add D_DVBAPI = -d128, eliminate cs_ptyp which complicates stuff unnecc

File size: 5.9 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
9LLIST_D_ *ac_stat_list = NULL; //struct s_acasc
10LLIST_D_ *acasc_list = NULL; //struct s_acasc_shm
11
12int ac_init_log(void)
13{
14 if( (!fpa) && (cfg->ac_logfile[0]))
15 {
16 if( (fpa=fopen(cfg->ac_logfile, "a+"))<=(FILE *)0 )
17 {
18 fpa=(FILE *)0;
19 fprintf(stderr, "can't open anti-cascading logfile: %s\n", cfg->ac_logfile);
20 }
21 else
22 cs_log("anti-cascading log initialized");
23 }
24
25 return(fpa<=(FILE *)0);
26}
27
28void ac_clear()
29{
30 llist_clear(acasc_list);
31 llist_clear(ac_stat_list);
32}
33
34void ac_done_stat()
35{
36 ac_clear();
37 llist_destroy(acasc_list);
38 llist_destroy(ac_stat_list);
39}
40
41void ac_init_stat()
42{
43 if (acasc_list)
44 ac_clear();
45 else {
46 ac_stat_list = llist_create();
47 acasc_list = llist_create();
48 }
49
50 if( fpa )
51 fclose(fpa);
52 fpa=(FILE *)0;
53 if( ac_init_log() )
54 cs_exit(0);
55}
56
57static struct s_client *idx_from_ac_idx(int ac_idx)
58{
59 struct s_client *cl;
60 for (cl=first_client; cl ; cl=cl->next)
61 if( cl->ac_idx==ac_idx )
62 return cl;
63 return NULL;
64}
65
66void ac_do_stat()
67{
68 int i, j, idx, exceeds, maxval, prev_deny=0;
69 struct s_client *cl_idx;
70
71 LLIST_D__ITR itr1, itr2;
72 i = 1;
73 struct s_acasc *ac_stat = llist_itr_init(ac_stat_list, &itr1);
74 struct s_acasc_shm *acasc = llist_itr_init(acasc_list, &itr2);
75 while (acasc)
76 {
77 int ac_stat_next = 1;
78 if (!ac_stat) {
79 ac_stat = malloc(sizeof(struct s_acasc));
80 memset(ac_stat, 0, sizeof(struct s_acasc));
81 llist_append(ac_stat_list, ac_stat);
82 ac_stat_next = 0;
83 }
84
85 idx = ac_stat->idx;
86 ac_stat->stat[idx] = acasc->ac_count;
87 acasc->ac_count=0;
88 cl_idx = idx_from_ac_idx(i);
89
90 if( ac_stat->stat[idx] && cl_idx)
91 {
92 //if( cl_idx == NULL ) {
93 //cs_log("ERROR: can't find client with ac_idx=%d", i);
94 //client is no longer connected
95 //}
96
97 if( cl_idx->ac_penalty==2 ) {// banned
98 cs_debug_mask(D_CLIENT, "user '%s' banned", cl_idx->usr);
99 acasc->ac_deny=1;
100 }
101 else
102 {
103 for( j=exceeds=maxval=0; j<cfg->ac_samples; j++ )
104 {
105 if( ac_stat->stat[j] > maxval )
106 maxval=ac_stat->stat[j];
107 exceeds+=(ac_stat->stat[j]>cl_idx->ac_limit);
108 }
109 prev_deny=acasc->ac_deny;
110 acasc->ac_deny = (exceeds >= cfg->ac_denysamples);
111
112 cs_debug_mask(D_CLIENT, "%s limit=%d, max=%d, samples=%d, dsamples=%d, ac[ci=%d][si=%d]:",
113 cl_idx->usr, cl_idx->ac_limit, maxval,
114 cfg->ac_samples, cfg->ac_denysamples, i, idx);
115 cs_debug_mask(D_CLIENT, "%d %d %d %d %d %d %d %d %d %d ", ac_stat->stat[0],
116 ac_stat->stat[1], ac_stat->stat[2], ac_stat->stat[3],
117 ac_stat->stat[4], ac_stat->stat[5], ac_stat->stat[6],
118 ac_stat->stat[7], ac_stat->stat[8], ac_stat->stat[9]);
119 if( acasc->ac_deny ) {
120 cs_log("user '%s' exceeds limit", cl_idx->usr);
121 ac_stat->stat[idx] = 0;
122 } else if( prev_deny )
123 cs_log("user '%s' restored access", cl_idx->usr);
124 }
125 }
126 else if( acasc->ac_deny )
127 {
128 prev_deny=1;
129 acasc->ac_deny=0;
130 if( cl_idx != NULL )
131 cs_log("restored access for inactive user '%s'", cl_idx->usr);
132 else
133 cs_log("restored access for unknown user (ac_idx=%d)", i);
134 }
135
136 if( !acasc->ac_deny && !prev_deny )
137 ac_stat->idx = (ac_stat->idx + 1) % cfg->ac_samples;
138
139 if (ac_stat_next)
140 ac_stat = llist_itr_next(&itr1);
141 else
142 ac_stat = NULL;
143 acasc = llist_itr_next(&itr2);
144 i++;
145 }
146}
147
148void ac_init_client(struct s_auth *account)
149{
150 struct s_client *cl = cur_client();
151 cl->ac_idx = account->ac_idx;
152 cl->ac_limit = 0;
153 if( cfg->ac_enabled )
154 {
155 if( account->ac_users )
156 {
157 cl->ac_limit = (account->ac_users*100+80)*cfg->ac_stime;
158 cl->ac_penalty = account->ac_penalty;
159 cs_debug_mask(D_CLIENT, "login '%s', ac_idx=%d, users=%d, stime=%d min, dwlimit=%d per min, penalty=%d",
160 account->usr, account->ac_idx, account->ac_users, cfg->ac_stime,
161 account->ac_users*100+80, account->ac_penalty);
162 }
163 else
164 {
165 cs_debug_mask(D_CLIENT, "anti-cascading not used for login '%s'", account->usr);
166 }
167 }
168}
169
170static int ac_dw_weight(ECM_REQUEST *er)
171{
172 struct s_cpmap *cpmap;
173
174 for( cpmap=cfg->cpmap; (cpmap) ; cpmap=cpmap->next )
175 if( (cpmap->caid ==0 || cpmap->caid ==er->caid) &&
176 (cpmap->provid==0 || cpmap->provid==er->prid) &&
177 (cpmap->sid ==0 || cpmap->sid ==er->srvid) &&
178 (cpmap->chid ==0 || cpmap->chid ==er->chid) )
179 return (cpmap->dwtime*100/60);
180
181 cs_debug_mask(D_CLIENT, "WARNING: CAID %04X, PROVID %06X, SID %04X, CHID %04X not found in oscam.ac",
182 er->caid, er->prid, er->srvid, er->chid);
183 cs_debug_mask(D_CLIENT, "set DW lifetime 10 sec");
184 return 16; // 10*100/60
185}
186
187struct s_acasc_shm *get_acasc(ushort ac_idx) {
188 int i=1;
189 LLIST_D__ITR itr;
190
191 struct s_acasc_shm *acasc = llist_itr_init(acasc_list, &itr);
192 while (acasc) {
193 if (i == ac_idx)
194 return acasc;
195 acasc = llist_itr_next(&itr);
196 i++;
197 }
198 acasc = malloc(sizeof(struct s_acasc_shm));
199 memset(acasc, 0, sizeof(struct s_acasc_shm));
200 llist_append(acasc_list, acasc);
201 return acasc;
202}
203
204void ac_chk(ECM_REQUEST *er, int level)
205{
206 struct s_client *cl = cur_client();
207 if (!cl->ac_limit || !cfg->ac_enabled ||!acasc_list) return;
208
209 struct s_acasc_shm *acasc = get_acasc(cl->ac_idx);
210
211 if( level==1 )
212 {
213 if( er->rc==7 ) acasc->ac_count++;
214 if( er->rc>3 ) return; // not found
215 if( memcmp(ac_ecmd5, er->ecmd5, CS_ECMSTORESIZE) != 0 )
216 {
217 acasc->ac_count+=ac_dw_weight(er);
218 memcpy(ac_ecmd5, er->ecmd5, CS_ECMSTORESIZE);
219 }
220 return;
221 }
222
223 if( acasc->ac_deny )
224 if( cl->ac_penalty )
225 {
226 cs_debug_mask(D_CLIENT, "send fake dw");
227 er->rc=7; // fake
228 er->rcEx=0;
229 cs_sleepms(cfg->ac_fakedelay);
230 }
231}
232#endif
Note: See TracBrowser for help on using the repository browser.