source: trunk/oscam-chk.c@ 8456

Last change on this file since 8456 was 8456, checked in by gf, 9 years ago

Slim down struct s_port.

struct s_port contains filter array and couple of other fields that are
used only for newcamd and nothing else. They waste more than 2k in common
case.

To stop losing this much space, create private structure only for
newcamd fields and allocate it dynamically. This lowers struct s_port
size a lot and of course struct s_ptab even more because it contains
array of struct s_ports's.

New structure sizes (32-bit):

                  before  after
  struct s_port     2144     12
  struct s_ptab    68612    388
  struct s_config 141260   4812

Size report (32-bit):

    text     data      bss      dec    hex filename
  998222     1944   602344  1602510 1873ce before/oscam-1.20-unstable_svn8453-i486-slackware-linux
  998174     1944    61800  1061918 10341e  after/oscam-1.20-unstable_svn8453-i486-slackware-linux

bloat-o-meter report (32-bit):

  add/remove: 0/1 grow/shrink: 13/16 up/down: 7897/-548383 (-540486)
  function                                     old     new   delta
  modules                                     1840    9520   +7680
  ...
  cfg                                       141260    4812 -136448
  static.ptab                               411672       - -411672
  • Property svn:eol-style set to LF
File size: 28.2 KB
Line 
1#include "globals.h"
2#include "oscam-chk.h"
3#include "oscam-ecm.h"
4#include "oscam-client.h"
5#include "oscam-net.h"
6#include "oscam-string.h"
7
8#define CS_NANO_CLASS 0xE2
9#define OK 1
10#define ERROR 0
11
12#ifdef WITH_CARDREADER
13static int32_t ecm_ratelimit_findspace(struct s_reader * reader, ECM_REQUEST *er, int32_t maxloop, int32_t reader_mode)
14{
15 int32_t h, foundspace = -1;
16 time_t actualtime = time(NULL);
17 for (h = 0; h < maxloop; h++) { // always release slots with srvid that are overtime, even if not called from reader module to maximize available slots!
18 if ((actualtime - reader->rlecmh[h].last >= reader->ratelimitseconds + reader->srvidholdseconds) && (reader->rlecmh[h].last !=-1)){
19 cs_debug_mask(D_TRACE, "ratelimiter srvid %04X released from slot #%d/%d of reader %s (%d>=%d ratelimitsec + %d sec srvidhold!)", reader->rlecmh[h].srvid, h+1, maxloop, reader->label, (int) (actualtime - reader->rlecmh[h].last), reader->ratelimitseconds, reader->srvidholdseconds);
20 reader->rlecmh[h].last = -1;
21 reader->rlecmh[h].srvid = -1;
22 }
23 }
24
25 for (h = 0; h < maxloop; h++) { // check if srvid is already in a slot
26 if (reader->rlecmh[h].srvid == er->srvid) {
27 cs_debug_mask(D_TRACE, "ratelimiter found srvid %04X for %d sec in slot #%d/%d of reader %s",er->srvid,
28 (int) (actualtime - reader->rlecmh[h].last), h+1, maxloop,reader->label);
29
30 // check ecmunique if enabled and ecmunique time is done
31 if(reader_mode && reader->ecmunique && (actualtime - reader->rlecmh[h].last < reader->ratelimitseconds)) {
32 if (memcmp(reader->rlecmh[h].ecmd5, er->ecmd5, CS_ECMSTORESIZE)){
33 char ecmd5[17*3];
34 cs_hexdump(0, reader->rlecmh[h].ecmd5, 16, ecmd5, sizeof(ecmd5));
35 cs_debug_mask(D_TRACE, "ratelimiter ecm %s in this slot for next %d seconds -> skipping this slot!", ecmd5, (int)
36 (reader->ratelimitseconds - (actualtime - reader->rlecmh[h].last)));
37 continue;
38 }
39 }
40 if (h > 0){
41 for (foundspace = 0; foundspace < h; foundspace++) { // check for free lower slot
42 if (reader->rlecmh[foundspace].last ==- 1) {
43 reader->rlecmh[h].srvid = -1;
44 reader->rlecmh[h].last = -1;
45 cs_debug_mask(D_TRACE, "ratelimiter moving srvid %04X to slot #%d/%d of reader %s",er->srvid, foundspace+1, maxloop, reader->label);
46 return foundspace; // moving to lower free slot!
47 }
48 }
49 }
50 return h; // Found but cant move to lower slot!
51 }
52 } // srvid not found in slots!
53 if (!reader_mode) return -1; // who's calling us? reader or some stat prober? If reader then register otherwise just report!
54 for (h = 0; h < maxloop; h++) { // check for free slot
55 if (reader->rlecmh[h].last ==- 1) {
56 cs_debug_mask(D_TRACE, "ratelimiter added srvid %04X to slot #%d/%d of reader %s", er->srvid, h+1, maxloop, reader->label);
57 return h; // free slot found -> assign it!
58 }
59 else cs_debug_mask(D_TRACE, "ratelimiter srvid %04X for %d seconds present in slot #%d/%d of reader %s", reader->rlecmh[h].srvid, (int) (actualtime - reader->rlecmh[h].last), h+1, maxloop, reader->label); //occupied slots
60 }
61
62 #ifdef HAVE_DVBAPI
63 /* Overide ratelimit priority for dvbapi request */
64 foundspace = -1;
65 if ((cfg.dvbapi_enabled == 1) && streq(er->client->account->usr, cfg.dvbapi_usr)) {
66 if ((reader->lastdvbapirateoverride) < (actualtime - reader->ratelimitseconds)) {
67 time_t minecmtime = actualtime;
68 for (h = 0; h < maxloop; h++) {
69 if(reader->rlecmh[h].last < minecmtime) {
70 minecmtime = reader->rlecmh[h].last;
71 foundspace = h;
72 }
73 }
74 reader->lastdvbapirateoverride = actualtime;
75 cs_debug_mask(D_TRACE, "prioritizing DVBAPI user %s over other watching client", er->client->account->usr);
76 cs_debug_mask(D_TRACE, "ratelimiter forcing srvid %04X into slot #%d/%d of reader %s", er->srvid, foundspace+1, maxloop, reader->label);
77 return foundspace;
78 } else cs_debug_mask(D_TRACE, "DVBAPI User %s is switching too fast for ratelimit and can't be prioritized!",
79 er->client->account->usr);
80 }
81 #endif
82
83 return (-1);
84}
85
86int32_t ecm_ratelimit_check(struct s_reader * reader, ECM_REQUEST *er, int32_t reader_mode)
87{
88 int32_t foundspace = 0, maxslots = MAXECMRATELIMIT; //init slots to oscam global maximums
89
90 if (!reader->ratelimitecm) return OK; /* no rate limit set */
91
92 if (reader->cooldown[0]) { // Do we use cooldown?
93 if (reader->cooldownstate == 1) { // Cooldown in ratelimit phase
94 maxslots = reader->ratelimitecm; // use user defined ratelimitecm
95 if (time(NULL) - reader->cooldowntime >= reader->cooldown[1]) { // check if cooldowntime is elapsed
96 reader->cooldownstate = 0; // set cooldown setup phase
97 reader->cooldowntime = 0; // reset cooldowntime
98 maxslots = MAXECMRATELIMIT; //use oscam defined max slots
99 cs_log("Reader: %s ratelimiter returning to setup phase cooling down period of %d seconds is done!", reader->label, reader->cooldown[1]);
100 }
101 }
102 }
103
104 if (reader_mode){
105 char ecmd5[17*3];
106 cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5));
107 cs_debug_mask(D_TRACE, "ratelimiter find a slot for srvid %04X ecm %s on reader %s", er->srvid, ecmd5, reader->label);
108 }
109 else {
110 cs_debug_mask(D_TRACE, "ratelimiter find a slot for srvid %04X on reader %s", er->srvid, reader->label);
111 }
112 foundspace = ecm_ratelimit_findspace(reader, er, maxslots, reader_mode);
113 if (foundspace < 0 || foundspace >= reader->ratelimitecm) { /* No space due to ratelimit */
114 if (!reader_mode) return OK; // who's calling us? reader or some stat prober? If reader then register otherwise just report!
115 if (reader->cooldown[0] && reader->cooldownstate == 0){ // we are in setup phase of cooldown
116 cs_log("Reader: %s ratelimiter detected overrun ecmratelimit of %d during setup phase!",reader->label, reader->ratelimitecm);
117 reader->cooldownstate = 2; /* Entering cooldowndelay phase */
118 reader->cooldowntime = time(NULL); // set cooldowntime to calculate delay
119 cs_debug_mask(D_TRACE, "ratelimiter cooldowndelaying %d seconds", reader->cooldown[0]);
120 if (foundspace < 0) return ERROR; //not even trowing an error... obvious reason ;)
121 reader->rlecmh[foundspace].last=time(NULL); // register new slot >ecmratelimit
122 reader->rlecmh[foundspace].srvid=er->srvid;
123 return OK;
124 }
125 if (reader->cooldown[0] && reader->cooldownstate == 2) { // check if cooldowndelay is elapsed
126 if (time(NULL) - reader->cooldowntime <= reader->cooldown[0]) { // we are in cooldowndelay!
127 if (foundspace < 0) return ERROR; //not even trowing an error... obvious reason ;)
128 if (reader_mode){ // who's calling us? reader or some stat prober? If reader then register otherwise just report!
129 reader->rlecmh[foundspace].last=time(NULL); // register new slot >ecmratelimit
130 reader->rlecmh[foundspace].srvid=er->srvid;
131 if(reader_mode) memcpy(reader->rlecmh[foundspace].ecmd5, er->ecmd5, CS_ECMSTORESIZE); // register ecmhash
132 }
133 return OK;
134 }
135 else {
136 if (!reader_mode) return ERROR; //who's calling us? reader or some stat prober? If reader then register otherwise just report!
137 reader->cooldownstate = 1; // Entering ratelimit for cooldown ratelimitseconds
138 reader->cooldowntime = time(NULL); // set time to enforce ecmratelimit for defined cooldowntime
139 cs_log("Reader: %s ratelimiter starting cooling down period of %d seconds!", reader->label, reader->cooldown[1]);
140
141 for (foundspace = reader->ratelimitecm; foundspace <= maxslots; foundspace++) { // release all slots above ratelimit
142 reader->rlecmh[foundspace].last = -1;
143 reader->rlecmh[foundspace].srvid = -1;
144 }
145 }
146 }
147 // Ratelimit and cooldown in ratelimitseconds
148 if (!reader_mode) return ERROR; //who's calling us? reader or some stat prober? If reader then register otherwise just report!
149 cs_debug_mask(D_TRACE, "ratelimiter no free slot for srvid %04X on reader %s -> dropping!", er->srvid, reader->label);
150 write_ecm_answer(reader, er, E_NOTFOUND, E2_RATELIMIT, NULL, "Ratelimiter: no slots free!");
151 return ERROR;
152 }
153 if (reader_mode) { //who's calling us? reader or some stat prober? If reader then register otherwise just report!
154 reader->rlecmh[foundspace].last=time(NULL); //we are within ecmratelimits
155 reader->rlecmh[foundspace].srvid=er->srvid;
156 memcpy(reader->rlecmh[foundspace].ecmd5, er->ecmd5, CS_ECMSTORESIZE);// register ecmhash
157 }
158 if (reader->cooldown[0] && reader->cooldownstate == 2) { // check if cooldowndelay is elapsed
159 if (time(NULL) - reader->cooldowntime > reader->cooldown[0]) {
160 reader->cooldownstate = 0; // return to cooldown setup phase
161 reader->cooldowntime = 0; // reset cooldowntime
162 maxslots = MAXECMRATELIMIT; //use oscam defined max slots
163 cs_log("Reader: %s ratelimiter returned to setup phase after %d seconds cooldowndelay!",reader->label, reader->cooldown[0]);
164 }
165 }
166 return OK;
167}
168#endif
169
170static int32_t find_nano(uchar *ecm, int32_t l, uchar nano, int32_t s)
171{
172 uchar *snano;
173
174 if( s >= l ) return 0;
175 if( !s ) s=(ecm[4]==0xD2) ? 12 : 9; // tpsflag -> offset+3
176 snano = ecm + s;
177
178 while( (*snano!=nano) && (s<l) )
179 {
180 if( *snano == 0xEA ) return 0;
181 snano++;
182 s++;
183 }
184
185 return (s<l)?++s:0;
186}
187
188static int32_t chk_class(ECM_REQUEST *er, CLASSTAB *clstab, const char *type, const char *name)
189{
190 int32_t i, j, an, cl_n, l;
191 uchar ecm_class;
192
193 if( er->caid!=0x0500 ) return 1;
194 if( !clstab->bn && !clstab->an ) return 1;
195
196 j=an=cl_n=l=0;
197 while( (j=find_nano(er->ecm, er->ecmlen, CS_NANO_CLASS, j)) > 0 )
198 {
199 l = er->ecm[j];
200 if(l+j>er->ecmlen) continue; // skip, this is not a valid class identifier!
201 ecm_class = er->ecm[j+l];
202 cs_debug_mask(D_CLIENT, "ecm class=%02X", ecm_class);
203 for( i=0; i<clstab->bn; i++ ) // search in blocked
204 if( ecm_class==clstab->bclass[i] )
205 {
206 cs_debug_mask(D_CLIENT, "class %02X rejected by %s '%s' !%02X filter",
207 ecm_class, type, name, ecm_class);
208 return 0;
209 }
210
211 cl_n++;
212 for( i=0; i<clstab->an; i++ ) // search in allowed
213 if( ecm_class==clstab->aclass[i] )
214 {
215 an++;
216 break;
217 }
218 j+=l;
219 }
220
221 if( cl_n && clstab->an )
222 {
223 if( an )
224 cs_debug_mask(D_CLIENT, "ECM classes allowed by %s '%s' filter", type, name);
225 else {
226 cs_debug_mask(D_CLIENT, "ECM classes don't match %s '%s' filter, rejecting", type, name);
227 return 0;
228 }
229 }
230
231 return 1;
232}
233
234int32_t chk_srvid_match(ECM_REQUEST *er, SIDTAB *sidtab)
235{
236 int32_t i, rc=0;
237
238 if (!sidtab->num_caid)
239 rc|=1;
240 else
241 for (i=0; (i<sidtab->num_caid) && (!(rc&1)); i++)
242 if (er->caid==sidtab->caid[i]) rc|=1;
243
244 if (!er->prid || !sidtab->num_provid)
245 rc|=2;
246 else
247 for (i=0; (i<sidtab->num_provid) && (!(rc&2)); i++)
248 if (er->prid==sidtab->provid[i]) rc|=2;
249
250 if (!sidtab->num_srvid)
251 rc|=4;
252 else
253 for (i=0; (i<sidtab->num_srvid) && (!(rc&4)); i++)
254 if (er->srvid==sidtab->srvid[i]) rc|=4;
255
256 return(rc==7);
257}
258
259int32_t chk_srvid(struct s_client *cl, ECM_REQUEST *er)
260{
261 int32_t nr, rc=0;
262 SIDTAB *sidtab;
263
264 if (!cl->sidtabs.ok)
265 {
266 if (!cl->sidtabs.no) return(1);
267 rc=1;
268 }
269 for (nr=0, sidtab=cfg.sidtab; sidtab; sidtab=sidtab->next, nr++)
270 if (sidtab->num_caid | sidtab->num_provid | sidtab->num_srvid)
271 {
272 if ((cl->sidtabs.no&((SIDTABBITS)1<<nr)) &&
273 (chk_srvid_match(er, sidtab)))
274 return(0);
275 if ((cl->sidtabs.ok&((SIDTABBITS)1<<nr)) &&
276 (chk_srvid_match(er, sidtab)))
277 rc=1;
278 }
279 return(rc);
280}
281
282int32_t has_srvid(struct s_client *cl, ECM_REQUEST *er) {
283 if (!cl->sidtabs.ok)
284 return 0;
285
286 int32_t nr;
287 SIDTAB *sidtab;
288
289 for (nr=0, sidtab=cfg.sidtab; sidtab; sidtab=sidtab->next, nr++)
290 if (sidtab->num_srvid)
291 {
292 if ((cl->sidtabs.ok&((SIDTABBITS)1<<nr)) &&
293 (chk_srvid_match(er, sidtab)))
294 return 1;
295 }
296 return 0;
297}
298
299
300int32_t chk_srvid_match_by_caid_prov(uint16_t caid, uint32_t provid, SIDTAB *sidtab)
301{
302 int32_t i, rc=0;
303
304 if (!sidtab->num_caid)
305 rc|=1;
306 else
307 for (i=0; (i<sidtab->num_caid) && (!(rc&1)); i++)
308 if (caid==sidtab->caid[i]) rc|=1;
309
310 if (!sidtab->num_provid)
311 rc|=2;
312 else
313 for (i=0; (i<sidtab->num_provid) && (!(rc&2)); i++)
314 if (provid==sidtab->provid[i]) rc|=2;
315
316 return(rc==3);
317}
318
319int32_t chk_srvid_by_caid_prov(struct s_client *cl, uint16_t caid, uint32_t provid) {
320 int32_t nr, rc=0;
321 SIDTAB *sidtab;
322
323 if (!cl->sidtabs.ok)
324 {
325 if (!cl->sidtabs.no) return(1);
326 rc=1;
327 }
328 for (nr=0, sidtab=cfg.sidtab; sidtab; sidtab=sidtab->next, nr++)
329 if (sidtab->num_caid | sidtab->num_provid)
330 {
331 if ((cl->sidtabs.no&((SIDTABBITS)1<<nr)) && !sidtab->num_srvid &&
332 (chk_srvid_match_by_caid_prov(caid, provid, sidtab)))
333 return(0);
334 if ((cl->sidtabs.ok&((SIDTABBITS)1<<nr)) &&
335 (chk_srvid_match_by_caid_prov(caid, provid, sidtab)))
336 rc=1;
337 }
338 return(rc);
339}
340
341int32_t chk_srvid_by_caid_prov_rdr(struct s_reader *rdr, uint16_t caid, uint32_t provid) {
342 int32_t nr, rc=0;
343 SIDTAB *sidtab;
344
345 if (!rdr->sidtabs.ok)
346 {
347 if (!rdr->sidtabs.no) return(1);
348 rc=1;
349 }
350 for (nr=0, sidtab=cfg.sidtab; sidtab; sidtab=sidtab->next, nr++)
351 if (sidtab->num_caid | sidtab->num_provid)
352 {
353 if ((rdr->sidtabs.no&((SIDTABBITS)1<<nr)) && !sidtab->num_srvid &&
354 (chk_srvid_match_by_caid_prov(caid, provid, sidtab)))
355 return(0);
356 if ((rdr->sidtabs.ok&((SIDTABBITS)1<<nr)) &&
357 (chk_srvid_match_by_caid_prov(caid, provid, sidtab)))
358 rc=1;
359 }
360 return(rc);
361}
362
363
364// server filter for newcamd
365int32_t chk_sfilter(ECM_REQUEST *er, PTAB *ptab)
366{
367 int32_t i, j, pi, rc=1;
368 uint16_t caid, scaid;
369 uint32_t prid, sprid;
370
371 if (!ptab) return(1);
372 struct s_client *cur_cl = cur_client();
373
374 caid = er->caid;
375 prid = er->prid;
376 pi = cur_cl->port_idx;
377
378 if (cfg.ncd_mgclient && ptab == &cfg.ncd_ptab)
379 return 1;
380
381 if (ptab->nports && ptab->ports[pi].ncd && ptab->ports[pi].ncd->ncd_ftab.nfilts)
382 {
383 for( rc=j=0; (!rc) && (j<ptab->ports[pi].ncd->ncd_ftab.nfilts); j++ )
384 {
385 scaid = ptab->ports[pi].ncd->ncd_ftab.filts[j].caid;
386 if (caid==0||(caid!=0 && caid==scaid))
387 {
388 for( i=0; (!rc) && i<ptab->ports[pi].ncd->ncd_ftab.filts[j].nprids; i++ )
389 {
390 sprid=ptab->ports[pi].ncd->ncd_ftab.filts[j].prids[i];
391 cs_debug_mask(D_CLIENT, "trying server filter %04X:%06X", scaid, sprid);
392 if (prid==sprid)
393 {
394 rc=1;
395 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by server filter %04X:%06X",
396 caid, prid, scaid, sprid);
397 }
398 }
399 }
400 }
401 if(!rc)
402 {
403 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by server filters", caid, prid);
404 snprintf( er->msglog, MSGLOGSIZE, "no server match %04X:%06X",
405 caid, (uint32_t) prid );
406
407 if (!er->rcEx) er->rcEx=(E1_LSERVER<<4)|E2_IDENT;
408 return(rc);
409 }
410 }
411 return (rc);
412}
413
414static int32_t chk_chid(ECM_REQUEST *er, FTAB *fchid, char *type, char *name)
415{
416 int32_t rc=1, i, j, found_caid=0;
417 if( !fchid->nfilts ) return 1;
418
419 for( i=rc=0; (!rc) && i<fchid->nfilts; i++ )
420 if( er->caid == fchid->filts[i].caid ) {
421 found_caid=1;
422 for( j=0; (!rc) && j<fchid->filts[i].nprids; j++ )
423 {
424 cs_debug_mask(D_CLIENT, "trying %s '%s' CHID filter %04X:%04X",
425 type, name, fchid->filts[i].caid, fchid->filts[i].prids[j]);
426 if( er->chid == fchid->filts[i].prids[j] )
427 {
428 cs_debug_mask(D_CLIENT, "%04X:%04X allowed by %s '%s' CHID filter %04X:%04X",
429 er->caid, er->chid, type, name, fchid->filts[i].caid,
430 fchid->filts[i].prids[j]);
431 rc=1;
432 }
433 }
434 }
435
436 if( !rc )
437 {
438 if (found_caid)
439 cs_debug_mask(D_CLIENT, "no match, %04X:%04X rejected by %s '%s' CHID filter(s)",
440 er->caid, er->chid, type, name);
441 else {
442 rc=1;
443 cs_debug_mask(D_CLIENT, "%04X:%04X allowed by %s '%s' CHID filter, CAID not spezified",
444 er->caid, er->chid, type, name);
445 }
446 }
447 return (rc);
448}
449
450int32_t chk_ufilters(ECM_REQUEST *er)
451{
452 int32_t i, j, rc;
453 uint16_t ucaid;
454 uint32_t uprid;
455 struct s_client *cur_cl = cur_client();
456
457 rc=1;
458 if( cur_cl->ftab.nfilts )
459 {
460 FTAB *f = &cur_cl->ftab;
461 for( i=rc=0; (!rc) && (i<f->nfilts); i++ )
462 {
463 ucaid = f->filts[i].caid;
464 if( er->caid==0 || ucaid==0 || (er->caid!=0 && er->caid==ucaid) )
465 {
466 for( j=rc=0; (!rc) && (j<f->filts[i].nprids); j++ )
467 {
468 uprid = f->filts[i].prids[j];
469 cs_debug_mask(D_CLIENT, "trying user '%s' filter %04X:%06X",
470 cur_cl->account->usr, ucaid, uprid);
471 if( er->prid == uprid )
472 {
473 rc=1;
474 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by user '%s' filter %04X:%06X",
475 er->caid, er->prid, cur_cl->account->usr, ucaid, uprid);
476 }
477 }
478 }
479 }
480 if( !rc ) {
481 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by user '%s' filters",
482 er->caid, er->prid, cur_cl->account->usr);
483 snprintf( er->msglog, MSGLOGSIZE, "no card support %04X:%06X",
484 er->caid, (uint32_t) er->prid );
485
486 if( !er->rcEx ) er->rcEx=(E1_USER<<4)|E2_IDENT;
487 return (rc);
488 }
489 }
490
491 if( !(rc=chk_class(er, &cur_cl->cltab, "user", cur_cl->account->usr)) ) {
492 if( !er->rcEx ) er->rcEx=(E1_USER<<4)|E2_CLASS;
493 }
494 else if( !(rc=chk_chid(er, &cur_cl->fchid, "user", cur_cl->account->usr)) )
495 if( !er->rcEx ) er->rcEx=(E1_USER<<4)|E2_CHID;
496
497 if( rc ) er->rcEx=0;
498
499 return (rc);
500}
501
502int32_t chk_rsfilter(struct s_reader * reader, ECM_REQUEST *er)
503{
504 int32_t i, rc=1;
505 uint16_t caid;
506 uint32_t prid;
507
508 if( reader->ncd_disable_server_filt )
509 {
510 cs_debug_mask(D_CLIENT, "%04X:%06X allowed - server filters disabled",
511 er->caid, er->prid);
512 return 1;
513 }
514
515 rc=prid=0;
516 caid = reader->caid;
517 if( caid==er->caid )
518 {
519 for( i=0; (!rc) && (i<reader->nprov); i++ )
520 {
521 prid = (uint32_t)((reader->prid[i][1]<<16) |
522 (reader->prid[i][2]<<8) |
523 (reader->prid[i][3]));
524 cs_debug_mask(D_CLIENT, "trying server '%s' filter %04X:%06X",
525 reader->device, caid, prid);
526 if( prid==er->prid )
527 {
528 rc=1;
529 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by server '%s' filter %04X:%06X",
530 er->caid, er->prid, reader->device, caid, prid);
531 }
532 }
533 }
534 if(!rc) {
535 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by server '%s' filters",
536 er->caid, er->prid, reader->device);
537 if( !er->rcEx ) er->rcEx=(E1_SERVER<<4)|E2_IDENT;
538 return 0;
539 }
540
541 return(rc);
542}
543
544int32_t chk_rfilter2(uint16_t rcaid, uint32_t rprid, struct s_reader *rdr)
545{
546 int32_t i, j, rc=1;
547 uint16_t caid=0;
548 uint32_t prid=0;
549
550 if( rdr->ftab.nfilts )
551 {
552 for( rc=i=0; (!rc) && (i<rdr->ftab.nfilts); i++ )
553 {
554 caid = rdr->ftab.filts[i].caid;
555 if( (caid!=0 && caid==rcaid) || caid==0 )
556 {
557 for( j=0; (!rc) && (j<rdr->ftab.filts[i].nprids); j++)
558 {
559 prid = rdr->ftab.filts[i].prids[j];
560 cs_debug_mask(D_CLIENT, "trying reader '%s' filter %04X:%06X",
561 rdr->label, caid, prid);
562 if( prid==rprid )
563 {
564 rc=1;
565 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by reader '%s' filter %04X:%06X",
566 rcaid, rprid, rdr->label, caid, prid);
567 }
568 }
569 }
570 }
571 if(!rc) {
572 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by reader '%s' filters",
573 rcaid, rprid, rdr->label);
574 return 0;
575 }
576 }
577
578 return(rc);
579}
580
581
582static int32_t chk_rfilter(ECM_REQUEST *er, struct s_reader *rdr)
583{
584 return chk_rfilter2(er->caid, er->prid, rdr);
585}
586
587int32_t chk_ctab(uint16_t caid, CAIDTAB *ctab) {
588 if (!caid || !ctab->caid[0])
589 return 1;
590
591 int32_t i;
592 for (i=0;i<CS_MAXCAIDTAB;i++)
593 {
594 if (!ctab->caid[i]) {
595 return 0;
596 }
597 if ((caid & ctab->mask[i]) == ctab->caid[i])
598 return 1;
599 }
600 return 0;
601}
602
603int32_t chk_ctab_ex(uint16_t caid, CAIDTAB *ctab) {
604 if (!caid || !ctab->caid[0])
605 return 0;
606
607 int32_t i;
608 for (i=0;i<CS_MAXCAIDTAB;i++)
609 {
610 if (!ctab->caid[i]) {
611 return 0;
612 }
613 if ((caid & ctab->mask[i]) == ctab->caid[i])
614 return 1;
615 }
616 return 0;
617}
618
619int32_t matching_reader(ECM_REQUEST *er, struct s_reader *rdr, int32_t slot) {
620 (void)slot; // Prevent warning about unused param slot, when WITH_CARDREADER is disabled
621 //simple checks first:
622 if (!er || !rdr)
623 return(0);
624
625 //reader active?
626 struct s_client *cl = rdr->client;
627 if (!cl || !rdr->enable)
628 return(0);
629
630 // if physical reader a card needs to be inserted
631 if (!is_network_reader(rdr) && rdr->card_status != CARD_INSERTED)
632 return(0);
633
634 //Checking connected & group valid:
635 struct s_client *cur_cl = er->client; //cur_client();
636
637#ifdef CS_CACHEEX
638 //To avoid cascading, a incoming cache request should not invoke a outgoing cache request:
639 if (rdr->cacheex.mode == 1 && cur_cl->auth && cur_cl->account->cacheex.mode == 1)
640 return (0);
641
642 //Cacheex=3 defines a Cacheex-only reader. never match them.
643 if (rdr->cacheex.mode == 3)
644 return (0);
645#endif
646
647 if (!(rdr->grp&cur_cl->grp))
648 return(0);
649
650 //Checking caids:
651 if ((!er->ocaid || !chk_ctab(er->ocaid, &rdr->ctab)) && !chk_ctab(er->caid, &rdr->ctab)) {
652 cs_debug_mask(D_TRACE, "caid %04X not found in caidlist reader %s", er->caid, rdr->label);
653 return 0;
654 }
655
656 if (!is_network_reader(rdr) && ((rdr->caid >> 8) != ((er->caid >> 8) & 0xFF) && (rdr->caid >> 8) != ((er->ocaid >> 8) & 0xFF)))
657 {
658 int i, caid_found = 0;
659 for (i = 0; i < 2; i++) {
660 if (rdr->csystem.caids[i] == er->caid || rdr->csystem.caids[i] == er->ocaid) {
661 caid_found = 1;
662 break;
663 }
664 }
665 if (!caid_found)
666 return 0;
667 }
668
669 //Supports long ecms?
670 if (er->ecmlen > 255 && is_network_reader(rdr) && !rdr->ph.large_ecm_support) {
671 cs_debug_mask(D_TRACE, "no large ecm support (l=%d) for reader %s", er->ecmlen, rdr->label);
672 return 0;
673 }
674
675
676 //Checking services:
677 if (!chk_srvid(rdr->client, er)) {
678 cs_debug_mask(D_TRACE, "service %04X not matching reader %s", er->srvid, rdr->label);
679 return(0);
680 }
681
682 //Checking ident:
683 if (er->prid && !chk_rfilter(er, rdr)) {
684 cs_debug_mask(D_TRACE, "r-filter reader %s", rdr->label);
685 return(0);
686 }
687
688 //Check ECM nanos:
689 if (!chk_class(er, &rdr->cltab, "reader", rdr->label)) {
690 cs_debug_mask(D_TRACE, "class filter reader %s", rdr->label);
691 return(0);
692 }
693
694
695 // CDS NL: check for right seca type
696 if (!is_network_reader(rdr) && er->caid == 0x100 && er->prid == 0x00006a &&
697 !(er->ecm[8] == 0x00 && er->ecm[9] == 0x00)) { // no empty ecm
698 if (er->ecm[8] == 0x00 && rdr->secatype == 2) {
699 cs_debug_mask(D_TRACE,"Error: this is a nagra/mediaguard3 ECM and readertype is seca2!");
700 return 0; // we dont send a nagra/mediaguard3 ecm to a seca2 reader!
701 }
702 if ((er->ecm[8] == 0x10) && (er->ecm[9] == 0x01) && rdr->secatype == 3){
703 cs_debug_mask(D_TRACE,"Error: this is a seca2 ECM and readertype is nagra/mediaguard3!");
704 return 0; // we dont send a seca2 ecm to a nagra/mediaguard3 reader!
705 }
706 }
707
708 //Checking chid:
709 if (!chk_chid(er, &rdr->fchid, "reader", rdr->label)) {
710 cs_debug_mask(D_TRACE, "chid filter reader %s", rdr->label);
711 return(0);
712 }
713
714 //Schlocke reader-defined function, reader-self-check
715 if (rdr->ph.c_available && !rdr->ph.c_available(rdr, AVAIL_CHECK_CONNECTED, er)) {
716 cs_debug_mask(D_TRACE, "reader unavailable %s", rdr->label);
717 return 0;
718 }
719
720 //Checking entitlements:
721 if (ll_count(rdr->ll_entitlements) > 0) {
722 LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
723 S_ENTITLEMENT *item;
724 int8_t found = 0;
725 while ((item=ll_iter_next(&itr))) {
726 //if (item->caid == er->caid && (!er->prid || !item->provid || item->provid == er->prid)) { //provid check causing problems?
727 if (item->caid == er->caid || item->caid == er->ocaid) { //... so check at least caid only
728 found =1;
729 break;
730 }
731 }
732 if (!found){
733 cs_debug_mask(D_TRACE, "entitlements check failed on reader %s", rdr->label);
734 return 0;
735 }
736 }
737
738 //Checking ecmlength:
739 if (rdr->ecmWhitelist && er->ecmlen) {
740 struct s_ecmWhitelist *tmp;
741 struct s_ecmWhitelistIdent *tmpIdent;
742 struct s_ecmWhitelistLen *tmpLen;
743 int8_t ok = 0, foundident = 0;
744 for(tmp = rdr->ecmWhitelist; tmp; tmp = tmp->next){
745 if(tmp->caid == 0 || tmp->caid == er->caid){
746 for(tmpIdent = tmp->idents; tmpIdent; tmpIdent = tmpIdent->next){
747 if(tmpIdent->ident == 0 || tmpIdent->ident == er->prid){
748 foundident = 1;
749 for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen = tmpLen->next){
750 if (tmpLen->len == er->ecmlen) {
751 ok = 1;
752 break;
753 }
754 }
755 }
756 }
757 }
758 }
759 if(foundident == 1 && ok == 0){
760 cs_debug_mask(D_TRACE, "ECM is not in ecmwhitelist of reader %s.",rdr->label);
761 rdr->ecmsfilteredlen += 1;
762 return(0);
763 }
764 }
765
766 // ECM Header Check
767 if (rdr->ecmHeaderwhitelist && er->ecmlen) {
768 int8_t byteok = 0;
769 int8_t entryok = 0;
770 int8_t foundcaid = 0;
771 int8_t foundprovid = 0;
772 int16_t len = 0;
773 int32_t i = 0;
774 int8_t skip = 0;
775 struct s_ecmHeaderwhitelist *tmp;
776 for(tmp = rdr->ecmHeaderwhitelist; tmp; tmp = tmp->next){
777 skip = 0;
778 byteok = 0;
779 entryok = 0;
780 len = 0;
781 if (tmp->caid == 0 || tmp->caid == er->caid){
782 foundcaid = 1; //-> caid was in list
783 //rdr_debug_mask(rdr, D_READER, "Headerwhitelist: found matching CAID: %04X in list", tmp->caid);
784 if (tmp->provid == 0 || tmp->provid == er->prid) {
785 foundprovid = 1; //-> provid was in list
786 //rdr_debug_mask(rdr, D_READER, "Headerwhitelist: found matching Provid: %06X in list", tmp->provid);
787 len = tmp->len;
788 for (i=0; i < len/2; i++){
789 if (tmp->header[i] == er->ecm[i]){
790 byteok = 1;
791 //rdr_debug_mask(rdr, D_READER, "ECM Byte: %i of ECMHeaderwhitelist is correct. (%02X = %02X Headerlen: %i)", i, er->ecm[i], tmp->header[i], len/2);
792 }
793 else {
794 byteok = 0;
795 //rdr_debug_mask(rdr, D_READER, "ECM Byte: %i of ECMHeaderwhitelist is not valid. (%02X != %02X Headerlen: %i)", i, er->ecm[i], tmp->header[i], len/2);
796 entryok = 0;
797 break;
798 }
799 if (i == len/2-1 && byteok == 1){
800 entryok = 1;
801 }
802
803 }
804 } else {
805 //rdr_debug_mask(rdr, D_READER, "ECMHeaderwhitelist: Provid: %06X not found in List-Entry -> skipping check", er->prid);
806 skip = 1;
807 continue;
808 }
809 } else {
810 //rdr_debug_mask(rdr, D_READER, "ECMHeaderwhitelist: CAID: %04X not found in List-Entry -> skipping check", er->caid);
811 skip = 1;
812 continue;
813 }
814 if (entryok == 1){
815 break;
816 }
817
818 }
819 if (foundcaid == 1 && foundprovid == 1 && byteok == 1 && entryok == 1){
820 //cs_log("ECM for %04X:%06X:%04X is valid for ECMHeaderwhitelist of reader %s.", er->caid, er->prid, er->srvid, rdr->label);
821 } else {
822 if (skip == 0 || (foundcaid == 1 && foundprovid == 1 && entryok == 0 && skip == 1)) {
823 cs_ddump_mask(D_TRACE, er->ecm, er->ecmlen,
824 "following ECM %04X:%06X:%04X was filtered by ECMHeaderwhitelist of Reader %s from User %s because of not matching Header:",
825 er->caid, er->prid, er->srvid, rdr->label, username(er->client));
826 rdr->ecmsfilteredhead += 1;
827 return(0);
828 }
829 }
830 }
831
832 //Simple ring connection check:
833
834 //Check ip source+dest:
835 if (cfg.block_same_ip && IP_EQUAL(cur_cl->ip, rdr->client->ip) &&
836 get_module(cur_cl)->listenertype != LIS_DVBAPI &&
837 is_network_reader(rdr))
838 {
839 cs_debug_mask(D_TRACE, "ECMs origin %s has the same ip as reader %s, blocked!", username(cur_cl), rdr->label);
840 return 0;
841 }
842
843 if (cfg.block_same_name && strcmp(username(cur_cl), rdr->label) == 0) {
844 cs_debug_mask(D_TRACE, "ECMs origin %s has the same name as reader %s, blocked!", username(cur_cl), rdr->label);
845 return 0;
846 }
847 #ifdef WITH_CARDREADER
848 cs_debug_mask(D_TRACE, "matching_reader became slot attribute of %d", slot);
849 if (!is_network_reader(rdr) && slot == 1) {
850 // just check ratelimiter & cooldown, but no srvid assignment in slot
851 if(ecm_ratelimit_check(rdr, er, 0) != OK) return 0; //just check ratelimiter & cooldown
852 }
853 #endif
854 //All checks done, reader is matching!
855 return(1);
856}
857
858int32_t chk_caid(uint16_t caid, CAIDTAB *ctab)
859{
860 int32_t n, rc;
861 for (rc = -1, n=0; (n < CS_MAXCAIDTAB) && (rc < 0); n++)
862 if ((caid & ctab->mask[n]) == ctab->caid[n])
863 rc = ctab->cmap[n] ? ctab->cmap[n] : caid;
864 return rc;
865}
866
867int32_t chk_caid_rdr(struct s_reader *rdr,uint16_t caid) {
868 if (is_network_reader(rdr)) {
869 return 1; //reader caid is not real caid
870 } else if (rdr->caid==caid) {
871 return 1;
872 }
873 return 0;
874}
875
876int32_t chk_bcaid(ECM_REQUEST *er, CAIDTAB *ctab)
877{
878 int32_t caid;
879 caid = chk_caid(er->caid, ctab);
880 if (caid < 0)
881 return 0;
882 er->caid = caid;
883 return 1;
884}
Note: See TracBrowser for help on using the repository browser.