source: trunk/oscam-chk.c@ 4149

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

oscam-chk, oscam-nano: cleanup + check threadsafety

File size: 10.9 KB
Line 
1#include "globals.h"
2
3#define CS_NANO_CLASS 0xE2
4
5static int find_nano(uchar *ecm, int l, uchar nano, int s)
6{
7 uchar *snano;
8
9 if( s >= l ) return 0;
10 if( !s ) s=(ecm[4]==0xD2) ? 12 : 9; // tpsflag -> offset+3
11 snano = ecm + s;
12
13 while( (*snano!=nano) && (s<l) )
14 {
15 if( *snano == 0xEA ) return 0;
16 snano++;
17 s++;
18 }
19
20 return (s<l)?++s:0;
21}
22
23static int chk_class(ECM_REQUEST *er, CLASSTAB *clstab, const char *D_USE(type), const char *D_USE(name))
24{
25 int i, j, an, cl_n, l;
26 uchar ecm_class;
27
28 if( er->caid!=0x0500 ) return 1;
29 if( !clstab->bn && !clstab->an ) return 1;
30
31 j=an=cl_n=l=0;
32 while( (j=find_nano(er->ecm, er->l, CS_NANO_CLASS, j)) > 0 )
33 {
34 l = er->ecm[j];
35 ecm_class = er->ecm[j+l];
36 cs_debug_mask(D_CLIENT, "ecm class=%02X", ecm_class);
37 for( i=0; i<clstab->bn; i++ ) // search in blocked
38 if( ecm_class==clstab->bclass[i] )
39 {
40 cs_debug_mask(D_CLIENT, "class %02X rejected by %s '%s' !%02X filter",
41 ecm_class, type, name, ecm_class);
42 return 0;
43 }
44
45 cl_n++;
46 for( i=0; i<clstab->an; i++ ) // search in allowed
47 if( ecm_class==clstab->aclass[i] )
48 {
49 an++;
50 break;
51 }
52 j+=l;
53 }
54
55 if( cl_n && clstab->an )
56 {
57 if( an )
58 cs_debug_mask(D_CLIENT, "ECM classes allowed by %s '%s' filter", type, name);
59 else {
60 cs_debug_mask(D_CLIENT, "ECM classes don't match %s '%s' filter, rejecting", type, name);
61 return 0;
62 }
63 }
64
65 return 1;
66}
67
68int chk_srvid_match(ECM_REQUEST *er, SIDTAB *sidtab)
69{
70 int i, rc=0;
71
72 if (!sidtab->num_caid)
73 rc|=1;
74 else
75 for (i=0; (i<sidtab->num_caid) && (!(rc&1)); i++)
76 if (er->caid==sidtab->caid[i]) rc|=1;
77
78 if (!sidtab->num_provid)
79 rc|=2;
80 else
81 for (i=0; (i<sidtab->num_provid) && (!(rc&2)); i++)
82 if (er->prid==sidtab->provid[i]) rc|=2;
83
84 if (!sidtab->num_srvid)
85 rc|=4;
86 else
87 for (i=0; (i<sidtab->num_srvid) && (!(rc&4)); i++)
88 if (er->srvid==sidtab->srvid[i]) rc|=4;
89
90 return(rc==7);
91}
92
93int chk_srvid(struct s_client *cl, ECM_REQUEST *er)
94{
95 int nr, rc=0;
96 SIDTAB *sidtab;
97
98 if (!cl->sidtabok)
99 {
100 if (!cl->sidtabno) return(1);
101 rc=1;
102 }
103 for (nr=0, sidtab=cfg->sidtab; sidtab; sidtab=sidtab->next, nr++)
104 if (sidtab->num_caid | sidtab->num_provid | sidtab->num_srvid)
105 {
106 if ((cl->sidtabno&((SIDTABBITS)1<<nr)) &&
107 (chk_srvid_match(er, sidtab)))
108 return(0);
109 if ((cl->sidtabok&((SIDTABBITS)1<<nr)) &&
110 (chk_srvid_match(er, sidtab)))
111 rc=1;
112 }
113 return(rc);
114}
115
116static int chk_srvid_match_by_caid_prov(ushort caid, ulong provid, SIDTAB *sidtab)
117{
118 int i, rc=0;
119
120 if (!sidtab->num_caid)
121 rc|=1;
122 else
123 for (i=0; (i<sidtab->num_caid) && (!(rc&1)); i++)
124 if (caid==sidtab->caid[i]) rc|=1;
125
126 if (!sidtab->num_provid)
127 rc|=2;
128 else
129 for (i=0; (i<sidtab->num_provid) && (!(rc&2)); i++)
130 if (provid==sidtab->provid[i]) rc|=2;
131
132 return(rc==3);
133}
134
135int chk_srvid_by_caid_prov(struct s_client *cl, ushort caid, ulong provid) {
136 int nr, rc=0;
137 SIDTAB *sidtab;
138
139 if (!cl->sidtabok)
140 {
141 if (!cl->sidtabno) return(1);
142 rc=1;
143 }
144 for (nr=0, sidtab=cfg->sidtab; sidtab; sidtab=sidtab->next, nr++)
145 if (sidtab->num_caid | sidtab->num_provid)
146 {
147 if ((cl->sidtabno&((SIDTABBITS)1<<nr)) && !sidtab->num_srvid &&
148 (chk_srvid_match_by_caid_prov(caid, provid, sidtab)))
149 return(0);
150 if ((cl->sidtabok&((SIDTABBITS)1<<nr)) &&
151 (chk_srvid_match_by_caid_prov(caid, provid, sidtab)))
152 rc=1;
153 }
154 return(rc);
155
156}
157
158// server filter for newcamd
159int chk_sfilter(ECM_REQUEST *er, PTAB *ptab)
160{
161 int i, j, pi, rc=1;
162 ushort caid, scaid;
163 ulong prid, sprid;
164
165 if (!ptab) return(1);
166
167 caid = er->caid;
168 prid = er->prid;
169 pi = cur_client()->port_idx;
170
171 if (ptab->nports && ptab->ports[pi].ftab.nfilts)
172 {
173 for( rc=j=0; (!rc) && (j<ptab->ports[pi].ftab.nfilts); j++ )
174 {
175 scaid = ptab->ports[pi].ftab.filts[j].caid;
176 if (caid==0||(caid!=0 && caid==scaid))
177 {
178 for( i=0; (!rc) && i<ptab->ports[pi].ftab.filts[j].nprids; i++ )
179 {
180 sprid=ptab->ports[pi].ftab.filts[j].prids[i];
181 cs_debug_mask(D_CLIENT, "trying server filter %04X:%06X", scaid, sprid);
182 if (prid==sprid)
183 {
184 rc=1;
185 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by server filter %04X:%06X",
186 caid, prid, scaid, sprid);
187 }
188 }
189 }
190 }
191 if(!rc)
192 {
193 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by server filters", caid, prid);
194 snprintf( er->msglog, MSGLOGSIZE, "no server match %04X:%06X",
195 caid, (unsigned int) prid );
196
197 if (!er->rcEx) er->rcEx=(E1_LSERVER<<4)|E2_IDENT;
198 return(rc);
199 }
200 }
201 return (rc);
202}
203
204static int chk_chid(ECM_REQUEST *er, FTAB *fchid, char *D_USE(type), char *D_USE(name))
205{
206 int rc=1, i, j;
207
208 if( (er->caid & 0xFF00)!=0x600 ) return 1;
209 if( !er->chid ) return 1;
210 if( !fchid->nfilts ) return 1;
211
212 for( i=rc=0; (!rc) && i<fchid->nfilts; i++ )
213 if( er->caid == fchid->filts[i].caid )
214 for( j=0; (!rc) && j<fchid->filts[i].nprids; j++ )
215 {
216 cs_debug_mask(D_CLIENT, "trying %s '%s' CHID filter %04X:%04X",
217 type, name, fchid->filts[i].caid, fchid->filts[i].prids[j]);
218 if( er->chid == fchid->filts[i].prids[j] )
219 {
220 cs_debug_mask(D_CLIENT, "%04X:%04X allowed by %s '%s' CHID filter %04X:%04X",
221 er->caid, er->chid, type, name, fchid->filts[i].caid,
222 fchid->filts[i].prids[j]);
223 rc=1;
224 }
225 }
226
227 if( !rc )
228 {
229 cs_debug_mask(D_CLIENT, "no match, %04X:%04X rejected by %s '%s' CHID filter(s)",
230 er->caid, er->chid, type, name);
231 }
232 return (rc);
233}
234
235int chk_ufilters(ECM_REQUEST *er)
236{
237 int i, j, rc;
238 ushort ucaid;
239 ulong uprid;
240
241 rc=1;
242 if( cur_client()->ftab.nfilts )
243 {
244 FTAB *f = &cur_client()->ftab;
245 for( i=rc=0; (!rc) && (i<f->nfilts); i++ )
246 {
247 ucaid = f->filts[i].caid;
248 if( er->caid==0 || ucaid==0 || (er->caid!=0 && er->caid==ucaid) )
249 {
250 for( j=rc=0; (!rc) && (j<f->filts[i].nprids); j++ )
251 {
252 uprid = f->filts[i].prids[j];
253 cs_debug_mask(D_CLIENT, "trying user '%s' filter %04X:%06X",
254 cur_client()->usr, ucaid, uprid);
255 if( er->prid == uprid )
256 {
257 rc=1;
258 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by user '%s' filter %04X:%06X",
259 er->caid, er->prid, cur_client()->usr, ucaid, uprid);
260 }
261 }
262 }
263 }
264 if( !rc ) {
265 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by user '%s' filters",
266 er->caid, er->prid, cur_client()->usr);
267 snprintf( er->msglog, MSGLOGSIZE, "no card support %04X:%06X",
268 er->caid, (unsigned int) er->prid );
269
270 if( !er->rcEx ) er->rcEx=(E1_USER<<4)|E2_IDENT;
271 return (rc);
272 }
273 }
274
275 if( !(rc=chk_class(er, &cur_client()->cltab, "user", cur_client()->usr)) ) {
276 if( !er->rcEx ) er->rcEx=(E1_USER<<4)|E2_CLASS;
277 }
278 else if( !(rc=chk_chid(er, &cur_client()->fchid, "user", cur_client()->usr)) )
279 if( !er->rcEx ) er->rcEx=(E1_USER<<4)|E2_CHID;
280
281 if( rc ) er->rcEx=0;
282
283 return (rc);
284}
285
286int chk_rsfilter(struct s_reader * reader, ECM_REQUEST *er)
287{
288 int i, rc=1;
289 ushort caid;
290 ulong prid;
291
292 if( reader->ncd_disable_server_filt )
293 {
294 cs_debug_mask(D_CLIENT, "%04X:%06X allowed - server filters disabled",
295 er->caid, er->prid);
296 return 1;
297 }
298
299 rc=prid=0;
300 caid = reader->caid[0];
301 if( caid==er->caid )
302 {
303 for( i=0; (!rc) && (i<reader->nprov); i++ )
304 {
305 prid = (ulong)((reader->prid[i][0]<<16) |
306 (reader->prid[i][1]<<8) |
307 (reader->prid[i][2]));
308 cs_debug_mask(D_CLIENT, "trying server '%s' filter %04X:%06X",
309 reader->device, caid, prid);
310 if( prid==er->prid )
311 {
312 rc=1;
313 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by server '%s' filter %04X:%06X",
314 er->caid, er->prid, reader->device, caid, prid);
315 }
316 }
317 }
318 if(!rc) {
319 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by server '%s' filters",
320 er->caid, er->prid, reader->device);
321 if( !er->rcEx ) er->rcEx=(E1_SERVER<<4)|E2_IDENT;
322 return 0;
323 }
324
325 return(rc);
326}
327
328static int chk_rfilter(ECM_REQUEST *er, struct s_reader *rdr)
329{
330 int i, j, rc=1;
331 ushort caid=0;
332 ulong prid=0;
333
334 if( rdr->ftab.nfilts )
335 {
336 for( rc=i=0; (!rc) && (i<rdr->ftab.nfilts); i++ )
337 {
338 caid = rdr->ftab.filts[i].caid;
339 if( (caid!=0 && caid==er->caid) || caid==0 )
340 {
341 for( j=0; (!rc) && (j<rdr->ftab.filts[i].nprids); j++)
342 {
343 prid = rdr->ftab.filts[i].prids[j];
344 cs_debug_mask(D_CLIENT, "trying reader '%s' filter %04X:%06X",
345 rdr->label, caid, prid);
346 if( prid==er->prid )
347 {
348 rc=1;
349 cs_debug_mask(D_CLIENT, "%04X:%06X allowed by reader '%s' filter %04X:%06X",
350 er->caid, er->prid, rdr->label, caid, prid);
351 }
352 }
353 }
354 }
355 if(!rc) {
356 cs_debug_mask(D_CLIENT, "no match, %04X:%06X rejected by reader '%s' filters",
357 er->caid, er->prid, rdr->label);
358 return 0;
359 }
360 }
361
362 return(rc);
363}
364
365int chk_ctab(ushort caid, CAIDTAB *ctab) {
366 if (!caid || !ctab->caid[0])
367 return 1;
368
369 int i;
370 for (i=0;i<CS_MAXCAIDTAB;i++)
371 {
372 if (!ctab->caid[i]) {
373 return 0;
374 }
375 if ((caid & ctab->mask[i]) == ctab->caid[i])
376 return 1;
377 }
378 return 0;
379}
380
381int matching_reader(ECM_REQUEST *er, struct s_reader *rdr) {
382 //Checking connected & group valid:
383 if (!((rdr->fd) && (rdr->grp&cur_client()->grp)))
384 return(0);
385
386 //Checking enabled and not deleted:
387 if (!rdr->enable || rdr->deleted) {
388 cs_debug_mask(D_TRACE, "reader disabled/deleted %s", rdr->label);
389 return(0);
390 }
391
392 //Schlocke reader-defined function, reader-self-check:
393 if (rdr->ph.c_available && !rdr->ph.c_available(rdr, AVAIL_CHECK_CONNECTED)) {
394 cs_debug_mask(D_TRACE, "reader unavailable %s", rdr->label);
395 return 0;
396 }
397
398 //Checking caids:
399 if (!chk_ctab(er->ocaid, &rdr->ctab) && !chk_ctab(er->caid, &rdr->ctab)) {
400 cs_debug_mask(D_TRACE, "caid %04X not found in caidlist reader %s", er->caid, rdr->label);
401 return 0;
402 }
403
404 //Checking services:
405 if (!chk_srvid(rdr->client, er)) {
406 cs_debug_mask(D_TRACE, "service %04X not matching reader %s", er->srvid, rdr->label);
407 return(0);
408 }
409
410 //Checking ident:
411 if (!chk_rfilter(er, rdr)) {
412 cs_debug_mask(D_TRACE, "r-filter reader %s", rdr->label);
413 return(0);
414 }
415
416 //Check ECM nanos:
417 if (!chk_class(er, &rdr->cltab, "reader", rdr->label)) {
418 cs_debug_mask(D_TRACE, "class filter reader %s", rdr->label);
419 return(0);
420 }
421
422 //Checking chid:
423 if (!chk_chid(er, &rdr->fchid, "reader", rdr->label)) {
424 cs_debug_mask(D_TRACE, "chid filter reader %s", rdr->label);
425 return(0);
426 }
427
428 //All checks done, reader is matching!
429 return(1);
430}
Note: See TracBrowser for help on using the repository browser.