source: trunk/module-camd35.c@ 1985

Last change on this file since 1985 was 1985, checked in by alno, 12 years ago

irdeto filter - replaced sa by first 2 bytes of serial, fix bug in CMD05 receive block nano

File size: 16.2 KB
Line 
1#include "globals.h"
2extern struct s_reader *reader;
3
4//CMD00 - ECM (request)
5//CMD01 - ECM (response)
6//CMD02 - EMM (in clientmode - set EMM, in server mode - EMM data) - obsolete
7//CMD03 - ECM (cascading request)
8//CMD04 - ECM (cascading response)
9//CMD05 - EMM (emm request) send cardata/cardinfo to client
10//CMD06 - EMM (incomming EMM in server mode)
11//CMD19 - EMM (incomming EMM in server mode) only seen with caid 0x1830
12//CMD08 - Stop sending requests to the server for current srvid,prvid,caid
13//CMD44 - MPCS/OScam internal error notification
14
15#define REQ_SIZE 328 // 256 + 20 + 0x34
16static uchar upwd[64]={0};
17static uchar *req;
18static int is_udp=1;
19
20static int camd35_send(uchar *buf)
21{
22 int l;
23 unsigned char rbuf[REQ_SIZE+15+4], *sbuf=rbuf+4;
24
25 if (!client[cs_idx].udp_fd) return(-1);
26 l=20+buf[1]+(((buf[0]==3) || (buf[0]==4)) ? 0x34 : 0);
27 memcpy(rbuf, client[cs_idx].ucrc, 4);
28 memcpy(sbuf, buf, l);
29 memset(sbuf+l, 0xff, 15); // set unused space to 0xff for newer camd3's
30 memcpy(sbuf+4, i2b(4, crc32(0L, sbuf+20, sbuf[1])), 4);
31 l=boundary(4, l);
32 cs_ddump(sbuf, l, "send %d bytes to %s", l, remote_txt());
33 aes_encrypt(sbuf, l);
34
35 if (is_udp)
36 return(sendto(client[cs_idx].udp_fd, rbuf, l+4, 0,
37 (struct sockaddr *)&client[cs_idx].udp_sa,
38 sizeof(client[cs_idx].udp_sa)));
39 else
40 return(send(client[cs_idx].udp_fd, rbuf, l+4, 0));
41}
42
43static int camd35_auth_client(uchar *ucrc)
44{
45 int rc=1;
46 ulong crc;
47 struct s_auth *account;
48
49 if (upwd[0])
50 return(memcmp(client[cs_idx].ucrc, ucrc, 4) ? 1 : 0);
51 client[cs_idx].crypted=1;
52 crc=(((ucrc[0]<<24) | (ucrc[1]<<16) | (ucrc[2]<<8) | ucrc[3]) & 0xffffffffL);
53 for (account=cfg->account; (account) && (!upwd[0]); account=account->next)
54 if (crc==crc32(0L, MD5((unsigned char *)account->usr, strlen(account->usr), NULL), 16))
55 {
56 memcpy(client[cs_idx].ucrc, ucrc, 4);
57 strcpy((char *)upwd, account->pwd);
58 aes_set_key((char *) MD5(upwd, strlen((char *)upwd), NULL));
59 rc=cs_auth_client(account, NULL);
60 }
61 return(rc);
62}
63
64static int camd35_recv(uchar *buf, int l)
65{
66 int rc, s, rs, n=0;
67 unsigned char recrc[4];
68 for (rc=rs=s=0; !rc; s++) switch(s)
69 {
70 case 0:
71 if (is_server)
72 {
73 if (!client[cs_idx].udp_fd) return(-9);
74 if (is_udp)
75 rs=recv_from_udpipe(buf);
76 else
77 rs=recv(client[cs_idx].udp_fd, buf, l, 0);
78 }
79 else
80 {
81 if (!client[cs_idx].udp_fd) return(-9);
82 rs=recv(client[cs_idx].udp_fd, buf, l, 0);
83 }
84 if (rs<24) rc=-1;
85 break;
86 case 1:
87 memcpy(recrc, buf, 4);
88 memmove(buf, buf+4, rs-=4);
89 switch (camd35_auth_client(recrc))
90 {
91 case 0: break; // ok
92 case 1: rc=-2; break; // unknown user
93 default: rc=-9; break; // error's from cs_auth()
94 }
95 break;
96 case 2:
97 aes_decrypt(buf, rs);
98 cs_ddump(buf, rs, "received %d bytes from %s", rs, remote_txt());
99 if (rs!=boundary(4, rs))
100 cs_debug("WARNING: packet size has wrong decryption boundary");
101 //n=(buf[0]==3) ? n=0x34 : 0; this was original, but statement below seems more logical -- dingo35
102 n=(buf[0]==3) ? 0x34 : 0;
103 n=boundary(4, n+20+buf[1]);
104 if (n<rs)
105 cs_debug("ignoring %d bytes of garbage", rs-n);
106 else
107 if (n>rs) rc=-3;
108 break;
109 case 3:
110 if (crc32(0L, buf+20, buf[1])!=b2i(4, buf+4)) rc=-4;
111 if (!rc) rc=n;
112 break;
113 }
114 if ((rs>0) && ((rc==-1)||(rc==-2)))
115 cs_ddump(buf, rs, "received %d bytes from %s (native)", rs, remote_txt);
116 client[cs_idx].last=time((time_t *) 0);
117 switch(rc)
118 {
119 case -1: cs_log("packet to small (%d bytes)", rs);
120 break;
121 case -2: cs_auth_client(0, "unknown user");
122 break;
123 case -3: cs_log("incomplete request !");
124 break;
125 case -4: cs_log("checksum error (wrong password ?)");
126 break;
127 }
128 return(rc);
129}
130
131/*
132 * server functions
133 */
134
135static void camd35_request_emm(ECM_REQUEST *er)
136{
137 int i, au;
138 time_t now;
139 static time_t last = 0;
140 static int disable_counter = 0;
141 static uchar lastserial[8] = {0,0,0,0,0,0,0,0};
142
143 au = client[cs_idx].au;
144 if ((au < 0) || (au > CS_MAXREADER))
145 return; // TODO
146
147 time(&now);
148 if (!memcmp(lastserial, reader[au].hexserial, 8))
149 if (abs(now-last) < 180) return;
150
151 memcpy(lastserial, reader[au].hexserial, 8);
152 last = now;
153
154 if (reader[au].caid[0])
155 {
156 disable_counter = 0;
157 log_emm_request(au);
158 }
159 else
160 if (disable_counter > 2)
161 return;
162 else
163 disable_counter++;
164
165 memset(mbuf, 0, sizeof(mbuf));
166 mbuf[2] = mbuf[3] = 0xff; // must not be zero
167 memcpy(mbuf + 8, i2b(2, er->srvid), 2);
168 memcpy(mbuf + 12, i2b(4, er->prid), 4);
169 memcpy(mbuf + 16, i2b(2, er->pid), 2);
170 mbuf[0] = 5;
171 mbuf[1] = 111;
172 if (reader[au].caid[0])
173 {
174 mbuf[39] = 1; // no. caids
175 mbuf[20] = reader[au].caid[0]>>8; // caid's (max 8)
176 mbuf[21] = reader[au].caid[0]&0xff;
177 memcpy(mbuf + 40, reader[au].hexserial, 6); // serial now 6 bytes
178 mbuf[47] = reader[au].nprov;
179 for (i = 0; i < reader[au].nprov; i++)
180 {
181 if (((reader[au].caid[0] >= 0x1700) && (reader[au].caid[0] <= 0x1799)) || // Betacrypt
182 ((reader[au].caid[0] >= 0x0600) && (reader[au].caid[0] <= 0x0699))) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
183 {
184 mbuf[48 + (i*5)] = reader[au].prid[i][0];
185 memcpy(&mbuf[50 + (i*5)], &reader[au].prid[i][1], 3);
186 }
187 else
188 {
189 mbuf[48 + (i * 5)] = reader[au].prid[i][2];
190 mbuf[49 + (i * 5)] =reader[au].prid[i][3];
191 memcpy(&mbuf[50 + (i * 5)], &reader[au].sa[i][0],4); // for conax we need at least 4 Bytes
192 }
193 }
194 //we think client/server protocols should deliver all information, and only readers should discard EMM
195 mbuf[128] = reader[au].blockemm_g;
196 mbuf[129] = reader[au].blockemm_s;
197 mbuf[130] = reader[au].blockemm_u;
198 mbuf[131] = reader[au].card_system; //Cardsystem for Oscam client
199 }
200 else // disable emm
201 mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1;
202
203 memcpy(mbuf + 10, mbuf + 20, 2);
204 camd35_send(mbuf); // send with data-len 111 for camd3 > 3.890
205 mbuf[1]++;
206 camd35_send(mbuf); // send with data-len 112 for camd3 < 3.890
207}
208
209static void camd35_send_dcw(ECM_REQUEST *er)
210{
211 uchar *buf;
212 buf=req+(er->cpti*REQ_SIZE); // get orig request
213
214 if (((er->rcEx > 0) || (er->rc == 8)) && !client[cs_idx].c35_suppresscmd08)
215 {
216 buf[0]=0x08;
217 buf[1]=2;
218 memset(buf+20, 0, buf[1]);
219 }
220 else
221 {
222 // Send CW
223 if ((er->rc < 4) || (er->rc == 7))
224 {
225 if (buf[0]==3)
226 memmove(buf+20+16, buf+20+buf[1], 0x34);
227 buf[0]++;
228 buf[1]=16;
229 memcpy(buf+20, er->cw, buf[1]);
230 }
231 else
232 {
233 // Send old CMD44 to prevent cascading problems with older mpcs/oscam versions
234 buf[0]=0x44;
235 buf[1]=0;
236 }
237 }
238 camd35_send(buf);
239 camd35_request_emm(er);
240}
241
242static void camd35_process_ecm(uchar *buf)
243{
244 ECM_REQUEST *er;
245 if (!(er=get_ecmtask()))
246 return;
247 er->l=buf[1];
248 memcpy(req+(er->cpti*REQ_SIZE), buf, 0x34+20+er->l); // save request
249 er->srvid=b2i(2, buf+ 8);
250 er->caid =b2i(2, buf+10);
251 er->prid =b2i(4, buf+12);
252 er->pid =b2i(2, buf+16);
253 memcpy(er->ecm, buf+20, er->l);
254 get_cw(er);
255}
256
257static void camd35_process_emm(uchar *buf)
258{
259 int au;
260 EMM_PACKET epg;
261 memset(&epg, 0, sizeof(epg));
262 au=client[cs_idx].au;
263 if ((au<0) || (au>CS_MAXREADER)) return; // TODO
264 epg.l=buf[1];
265 memcpy(epg.caid , buf+10 , 2);
266 memcpy(epg.provid , buf+12 , 4);
267 memcpy(epg.emm , buf+20 , epg.l);
268 do_emm(&epg);
269}
270
271static void camd35_server()
272{
273 int n;
274
275 req=(uchar *)malloc(CS_MAXPENDING*REQ_SIZE);
276 if (!req)
277 {
278 cs_log("Cannot allocate memory (errno=%d)", errno);
279 cs_exit(1);
280 }
281 memset(req, 0, CS_MAXPENDING*REQ_SIZE);
282
283 is_udp = (ph[client[cs_idx].ctyp].type == MOD_CONN_UDP);
284
285 while ((n=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>0)
286 {
287 switch(mbuf[0])
288 {
289 case 0: // ECM
290 case 3: // ECM (cascading)
291 camd35_process_ecm(mbuf);
292 break;
293 case 6: // EMM
294 case 19: // EMM
295 camd35_process_emm(mbuf);
296 break;
297 default:
298 cs_log("unknown camd35 command! (%d)", mbuf[0]);
299 }
300 }
301
302 if(req) { free(req); req=0;}
303
304 cs_disconnect_client();
305}
306
307/*
308 * client functions
309 */
310
311static void casc_set_account()
312{
313 strcpy((char *)upwd, reader[ridx].r_pwd);
314 memcpy(client[cs_idx].ucrc, i2b(4, crc32(0L, MD5((unsigned char *)reader[ridx].r_usr, strlen(reader[ridx].r_usr), NULL), 16)), 4);
315 aes_set_key((char *)MD5(upwd, strlen((char *)upwd), NULL));
316 client[cs_idx].crypted=1;
317}
318
319int camd35_client_init()
320{
321 static struct sockaddr_in loc_sa;
322 struct protoent *ptrp;
323 int p_proto;//, sock_type;
324 char ptxt[16];
325
326 pfd=0;
327 if (reader[ridx].r_port<=0)
328 {
329 cs_log("invalid port %d for server %s", reader[ridx].r_port, reader[ridx].device);
330 return(1);
331 }
332 is_udp=(reader[ridx].typ==R_CAMD35);
333 if( (ptrp=getprotobyname(is_udp ? "udp" : "tcp")) )
334 p_proto=ptrp->p_proto;
335 else
336 p_proto=(is_udp) ? 17 : 6; // use defaults on error
337
338 client[cs_idx].ip=0;
339 memset((char *)&loc_sa,0,sizeof(loc_sa));
340 loc_sa.sin_family = AF_INET;
341#ifdef LALL
342 if (cfg->serverip[0])
343 loc_sa.sin_addr.s_addr = inet_addr(cfg->serverip);
344 else
345#endif
346 loc_sa.sin_addr.s_addr = INADDR_ANY;
347 loc_sa.sin_port = htons(reader[ridx].l_port);
348
349 if ((client[cs_idx].udp_fd=socket(PF_INET, is_udp ? SOCK_DGRAM : SOCK_STREAM, p_proto))<0)
350 {
351 cs_log("Socket creation failed (errno=%d)", errno);
352 cs_exit(1);
353 }
354
355#ifdef SO_PRIORITY
356 if (cfg->netprio)
357 setsockopt(client[cs_idx].udp_fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg->netprio, sizeof(ulong));
358#endif
359
360 if (reader[ridx].l_port>0)
361 {
362 if (bind(client[cs_idx].udp_fd, (struct sockaddr *)&loc_sa, sizeof (loc_sa))<0)
363 {
364 cs_log("bind failed (errno=%d)", errno);
365 close(client[cs_idx].udp_fd);
366 return(1);
367 }
368 sprintf(ptxt, ", port=%d", reader[ridx].l_port);
369 }
370 else
371 ptxt[0]='\0';
372
373 casc_set_account();
374 memset((char *)&client[cs_idx].udp_sa, 0, sizeof(client[cs_idx].udp_sa));
375 client[cs_idx].udp_sa.sin_family=AF_INET;
376 client[cs_idx].udp_sa.sin_port=htons((u_short)reader[ridx].r_port);
377
378 cs_log("proxy %s:%d (fd=%d%s)",
379 reader[ridx].device, reader[ridx].r_port,
380 client[cs_idx].udp_fd, ptxt);
381
382 if (is_udp) pfd=client[cs_idx].udp_fd;
383
384 return(0);
385}
386
387int camd35_client_init_log()
388{
389 static struct sockaddr_in loc_sa;
390 struct protoent *ptrp;
391 int p_proto;
392
393 if (reader[ridx].log_port<=0)
394 {
395 cs_log("invalid port %d for camd3-loghost", reader[ridx].log_port);
396 return(1);
397 }
398
399 ptrp=getprotobyname("udp");
400 if (ptrp)
401 p_proto=ptrp->p_proto;
402 else
403 p_proto=17; // use defaults on error
404
405 memset((char *)&loc_sa,0,sizeof(loc_sa));
406 loc_sa.sin_family = AF_INET;
407 loc_sa.sin_addr.s_addr = INADDR_ANY;
408 loc_sa.sin_port = htons(reader[ridx].log_port);
409
410 if ((logfd=socket(PF_INET, SOCK_DGRAM, p_proto))<0)
411 {
412 cs_log("Socket creation failed (errno=%d)", errno);
413 return(1);
414 }
415
416 if (bind(logfd, (struct sockaddr *)&loc_sa, sizeof(loc_sa))<0)
417 {
418 cs_log("bind failed (errno=%d)", errno);
419 close(logfd);
420 return(1);
421 }
422
423 cs_log("camd3 loghost initialized (fd=%d, port=%d)",
424 logfd, reader[ridx].log_port);
425
426 return(0);
427}
428
429static int tcp_connect()
430{
431 if (!reader[ridx].tcp_connected)
432 {
433 int handle=0;
434 handle = network_tcp_connection_open();
435 if (handle<0) return(0);
436
437 reader[ridx].tcp_connected = 1;
438 reader[ridx].last_s = reader[ridx].last_g = time((time_t *)0);
439 pfd = client[cs_idx].udp_fd = handle;
440 }
441 if (!client[cs_idx].udp_fd) return(0);
442 return(1);
443}
444
445static int camd35_send_ecm(ECM_REQUEST *er, uchar *buf)
446{
447 if (!client[cs_idx].udp_sa.sin_addr.s_addr) // once resolved at least
448 return(-1);
449
450 if (!is_udp && !tcp_connect()) return(-1);
451
452 memset(buf, 0, 20);
453 memset(buf+20, 0xff, er->l+15);
454 buf[1]=er->l;
455 memcpy(buf+ 8, i2b(2, er->srvid), 2);
456 memcpy(buf+10, i2b(2, er->caid ), 2);
457 memcpy(buf+12, i2b(4, er->prid ), 4);
458// memcpy(buf+16, i2b(2, er->pid ), 2);
459// memcpy(buf+16, &er->idx , 2);
460 memcpy(buf+16, i2b(2, er->idx ), 2);
461 buf[18]=0xff;
462 buf[19]=0xff;
463 memcpy(buf+20, er->ecm , er->l);
464 return((camd35_send(buf)<1) ? (-1) : 0);
465}
466
467static int camd35_send_emm(EMM_PACKET *ep)
468{
469 uchar buf[512];
470 if (!client[cs_idx].udp_sa.sin_addr.s_addr) // once resolved at least
471 return(-1);
472
473 if (!is_udp && !tcp_connect()) return(-1);
474
475 memset(buf, 0, 20);
476 memset(buf+20, 0xff, ep->l+15);
477
478 buf[0]=0x06;
479 buf[1]=ep->l;
480 memcpy(buf+10, ep->caid, 2);
481 memcpy(buf+12, ep->provid, 4);
482 memcpy(buf+20, ep->emm, ep->l);
483
484 return((camd35_send(buf)<1) ? (-1) : 0);
485}
486
487static int camd35_recv_chk(uchar *dcw, int *rc, uchar *buf)
488{
489 ushort idx;
490
491 // reading CMD05 Emm request and set serial
492 if ((buf[0] == 0x05) && !(buf[131]==0xff)) {
493
494 reader[ridx].nprov = 0; //reset if number changes on reader change
495 reader[ridx].nprov = buf[47];
496 reader[ridx].aucaid = b2i(2, buf+20);
497
498 int i;
499 for (i=0; i<reader[ridx].nprov; i++) {
500 if (((reader[ridx].aucaid >= 0x1700) && (reader[ridx].aucaid <= 0x1799)) || // Betacrypt
501 ((reader[ridx].aucaid >= 0x0600) && (reader[ridx].aucaid <= 0x0699))) // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
502 {
503 reader[ridx].prid[i][0] = buf[48 + (i*5)];
504 memcpy(&reader[ridx].prid[i][1], &buf[50 + (i * 5)], 3);
505 } else {
506 reader[ridx].prid[i][2] = buf[48 + (i * 5)];
507 reader[ridx].prid[i][3] = buf[49+ (i * 5)];
508 memcpy(&reader[ridx].sa[i][0], &buf[50 + (i * 5)], 4);
509 }
510 }
511
512 memcpy(reader[ridx].hexserial, buf + 40, 6);
513 reader[ridx].hexserial[6] = 0;
514 reader[ridx].hexserial[7] = 0;
515
516 reader[ridx].blockemm_g = buf[128];
517 reader[ridx].blockemm_s = buf[129];
518 reader[ridx].blockemm_u = buf[130];
519 reader[ridx].card_system = buf[131];
520 cs_log("CMD05 reader: %s serial: %s cardsyst: %d aucaid: %04X",
521 reader[ridx].label,
522 cs_hexdump(0, reader[ridx].hexserial, 8),
523 reader[ridx].card_system,
524 reader[ridx].aucaid);
525 }
526
527 // CMD44: old reject command introduced in mpcs
528 // keeping this for backward compatibility
529 if ((buf[0] != 1) && (buf[0] != 0x44) && (buf[0] != 0x08))
530 return(-1);
531
532 idx = b2i(2, buf+16);
533
534 *rc = ((buf[0] != 0x44) && (buf[0] != 0x08));
535
536 memcpy(dcw, buf+20, 16);
537 return(idx);
538}
539
540static int camd35_recv_log(ushort *caid, ulong *provid, ushort *srvid)
541{
542 int i;
543 uchar buf[512], *ptr, *ptr2;
544 ushort idx=0;
545 if (!logfd) return(-1);
546 if ((i=recv(logfd, buf, sizeof(buf), 0))<=0) return(-1);
547 buf[i]=0;
548
549 if (!(ptr=(uchar *)strstr((char *)buf, " -> "))) return(-1);
550 ptr+=4;
551 if (strstr((char *)ptr, " decoded ")) return(-1); // skip "found"s
552 if (!(ptr2=(uchar *)strchr((char *)ptr, ' '))) return(-1); // corrupt
553 *ptr2=0;
554
555 for (i=0, ptr2=(uchar *)strtok((char *)ptr, ":"); ptr2; i++, ptr2=(uchar *)strtok(NULL, ":"))
556 {
557 trim((char *)ptr2);
558 switch(i)
559 {
560 case 0: *caid =cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
561 case 1: *provid=cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
562 case 2: *srvid =cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
563 case 3: idx =cs_atoi((char *)ptr2, strlen((char *)ptr2)>>1, 0); break;
564 }
565 if (errno) return(-1);
566 }
567 return(idx&0x1FFF);
568}
569
570/*
571 * module definitions
572 */
573
574void module_camd35(struct s_module *ph)
575{
576 static PTAB ptab;
577 ptab.ports[0].s_port = cfg->c35_port;
578 ph->ptab = &ptab;
579 ph->ptab->nports = 1;
580
581 strcpy(ph->desc, "camd 3.5x");
582 ph->type=MOD_CONN_UDP;
583 ph->multi=1;
584 ph->watchdog=1;
585 ph->s_ip=cfg->c35_srvip;
586 ph->s_handler=camd35_server;
587 ph->recv=camd35_recv;
588 ph->send_dcw=camd35_send_dcw;
589 ph->c_multi=1;
590 ph->c_init=camd35_client_init;
591 ph->c_recv_chk=camd35_recv_chk;
592 ph->c_send_ecm=camd35_send_ecm;
593 ph->c_send_emm=camd35_send_emm;
594 ph->c_init_log=camd35_client_init_log;
595 ph->c_recv_log=camd35_recv_log;
596}
597
598void module_camd35_tcp(struct s_module *ph)
599{
600 strcpy(ph->desc, "cs378x");
601 ph->type=MOD_CONN_TCP;
602 ph->multi=1;
603 ph->watchdog=1;
604 ph->ptab=&cfg->c35_tcp_ptab;
605 if (ph->ptab->nports==0)
606 ph->ptab->nports=1; // show disabled in log
607 ph->s_ip=cfg->c35_tcp_srvip;
608 ph->s_handler=camd35_server;
609 ph->recv=camd35_recv;
610 ph->send_dcw=camd35_send_dcw;
611 ph->c_multi=1;
612 ph->c_init=camd35_client_init;
613 ph->c_recv_chk=camd35_recv_chk;
614 ph->c_send_ecm=camd35_send_ecm;
615 ph->c_send_emm=camd35_send_emm;
616 ph->c_init_log=camd35_client_init_log;
617 ph->c_recv_log=camd35_recv_log;
618}
Note: See TracBrowser for help on using the repository browser.