Attempt to count descramblers used properly
[oscam.git] / module-scam.c
blob368fab08610c332313343c4ba1255d7b02e0fe46
1 #define MODULE_LOG_PREFIX "scam"
3 #include "globals.h"
4 #ifdef MODULE_SCAM
5 #include "oscam-client.h"
6 #include "oscam-ecm.h"
7 #include "oscam-net.h"
8 #include "oscam-string.h"
9 #include "oscam-reader.h"
10 #include "oscam-lock.h"
11 #include "oscam-time.h"
12 #include "oscam-chk.h"
13 #include "cscrypt/des.h"
15 struct scam_data
17 uint8_t enckey[8];
18 uint8_t deckey[8];
19 uint8_t enc_xor_offset;
20 uint8_t dec_xor_offset;
21 uint8_t login_pending;
22 char login_username[64];
23 uint16_t version;
26 static inline void xxor(uint8_t *data, int32_t len, const uint8_t *v1, const uint8_t *v2)
28 uint32_t i;
29 switch(len)
31 case 16:
32 for(i = 0; i < 16; ++i)
34 data[i] = v1[i] ^ v2[i];
36 break;
38 case 8:
39 for(i = 0; i < 8; ++i)
41 data[i] = v1[i] ^ v2[i];
43 break;
45 case 4:
46 for(i = 0; i < 4; ++i)
48 data[i] = v1[i] ^ v2[i];
50 break;
52 default:
53 while(len--)
55 *data++ = *v1++ ^ *v2++;
57 break;
61 static void scam_generate_deskey(char *keyString, uint8_t *desKey)
63 uint8_t iv[8], *tmpKey;
64 int32_t i, passLen, alignedPassLen;
65 uint32_t key_schedule[32];
67 memset(iv, 0, 8);
68 memset(desKey, 0, 8);
70 passLen = keyString == NULL ? 0 : strlen(keyString);
71 if(passLen > 1024) {
72 passLen = 1024;
75 alignedPassLen = (passLen + 7) & -8;
76 if(alignedPassLen == 0) alignedPassLen = 8;
78 if(!cs_malloc(&tmpKey, alignedPassLen))
80 return;
83 if(passLen == 0)
85 memset(tmpKey, 0xAA, 8);
86 passLen = 8;
88 else
90 memcpy(tmpKey, keyString, passLen);
93 for(i = 0; i < alignedPassLen - passLen; i++)
95 tmpKey[passLen + i] = (uint8_t)i;
98 xxor(desKey, 8, tmpKey, iv);
100 for(i = 0; i < alignedPassLen; i += 8)
102 des_set_key(&tmpKey[i], key_schedule);
103 des(&tmpKey[i], key_schedule, 1);
104 xxor(desKey, 8, desKey, &tmpKey[i]);
107 NULLFREE(tmpKey);
110 static void scam_encrypt_packet(uint8_t *packet, uint32_t packetLength, uint8_t *key, uint32_t dataLength, uint32_t dataOffset, uint8_t *xorOffset)
112 uint8_t iv[8];
113 uint32_t i;
114 memset(iv, 0, 8);
116 des_cbc_encrypt(packet + dataOffset, iv, key, dataLength);
118 for(i = 0; i < packetLength; i++)
120 key[*xorOffset] ^= packet[i];
121 *xorOffset = (*xorOffset + 1) & 7;
125 static void scam_decrypt_packet(uint8_t *packet, uint32_t packetLength, uint8_t *key, uint32_t dataLength, uint32_t dataOffset, uint8_t *xorOffset)
127 uint8_t tmpKey[8], iv[8];
128 uint32_t i;
129 memcpy(tmpKey, key, 8);
130 memset(iv, 0, 8);
132 for(i = 0; i < packetLength; i++)
134 tmpKey[*xorOffset] ^= packet[i];
135 *xorOffset = (*xorOffset + 1) & 7;
138 des_cbc_decrypt(packet + dataOffset, iv, key, dataLength);
139 memcpy(key, tmpKey, 8);
142 static void scam_decode_length(uint8_t *packet, uint32_t *dataLength, uint32_t *dataOffset)
144 uint32_t i, n;
146 if(packet[1] & 0x80)
148 n = packet[1] & ~0x80;
149 *dataLength = 0;
151 for(i = 0; i < n; i++)
153 *dataLength = (*dataLength << 8) | packet[2 + i];
155 *dataOffset = 2 + n;
157 else
159 *dataLength = packet[1];
160 *dataOffset = 2;
164 static uint32_t scam_get_length_data_length(uint8_t *packet)
166 if(packet[1] & 0x80)
168 return packet[1] & ~0x80;
170 else
172 return 1;
176 static void scam_encode_length(uint32_t len, uint8_t *data, uint8_t *dataLen)
178 if(len < 128)
180 data[0] = (uint8_t)len;
181 *dataLen = 1;
183 else if(len < 256)
185 data[0] = 0x81;
186 data[1] = (uint8_t)len;
187 *dataLen = 2;
189 else if(len < 65536)
191 data[0] = 0x82;
192 data[1] = (uint8_t)(len >> 8);
193 data[2] = (uint8_t)(len & 0xFF);
194 *dataLen = 3;
196 else if(len < 16777216)
198 data[0] = 0x83;
199 data[1] = (uint8_t)(len >> 16);
200 data[2] = (uint8_t)((len >> 8) & 0xFF);
201 data[3] = (uint8_t)(len & 0xFF);
202 *dataLen = 4;
204 else
206 data[0] = 0x84;
207 data[1] = (uint8_t)(len >> 24);
208 data[2] = (uint8_t)((len >> 16) & 0xFF);
209 data[3] = (uint8_t)((len >> 8) & 0xFF);
210 data[4] = (uint8_t)(len & 0xFF);
211 *dataLen = 5;
216 static void scam_client_close(struct s_client *cl, int32_t call_conclose)
218 struct s_reader *rdr = cl->reader;
219 if(!rdr) { return; }
221 if(rdr) { rdr->tcp_connected = 0; }
222 if(rdr) { rdr->card_status = NO_CARD; }
223 if(rdr) { rdr->last_s = rdr->last_g = 0; }
224 if(cl) { cl->last = 0; }
226 if(call_conclose) // clears also pending ecms!
227 { network_tcp_connection_close(rdr, "close"); }
228 else
230 if(cl->udp_fd)
232 close(cl->udp_fd);
233 cl->udp_fd = 0;
234 cl->pfd = 0;
239 static int32_t scam_send(struct s_client *cl, uint8_t *buf, uint32_t len)
241 uint8_t *mbuf, lenData[5];
242 uint8_t lenDataLen = 0, paddingLen = 0;
243 uint16_t crc = 0;
244 int32_t result, packetLen;
245 struct scam_data *scam = cl->scam;
247 if(scam == NULL) { return 0; }
248 if(len == 0) { return 0; }
250 paddingLen = 8 - ((4 + len) % 8);
251 if(paddingLen == 8)
253 paddingLen = 0;
255 else if(paddingLen > 0 && paddingLen < 3)
257 paddingLen += 8;
260 scam_encode_length(4 + len + paddingLen, lenData, &lenDataLen);
262 if(lenDataLen == 0) { return -1; }
264 packetLen = 1 + lenDataLen + 4 + len + paddingLen;
266 if(!cs_malloc(&mbuf, packetLen)) { return -1; }
268 mbuf[0] = 0x0F;
269 memcpy(&mbuf[1], lenData, lenDataLen);
270 mbuf[1 + lenDataLen] = 0x10;
271 mbuf[1 + lenDataLen + 1] = 0x02;
272 memcpy(&mbuf[1 + lenDataLen + 4], buf, len);
274 if(paddingLen > 0)
276 mbuf[1 + lenDataLen + 4 + len] = 0x7F;
277 mbuf[1 + lenDataLen + 4 + len + 1] = paddingLen - 2;
278 get_random_bytes(mbuf + 1 + lenDataLen + 4 + len + 2, paddingLen - 2);
281 crc = ccitt_crc(mbuf + 1 + lenDataLen + 4, len + paddingLen, 0xFFFF, 0);
282 i2b_buf(2, crc, &mbuf[1 + lenDataLen + 2]);
284 scam_encrypt_packet(mbuf, packetLen, scam->enckey, 4 + len + paddingLen, 1 + lenDataLen, &scam->enc_xor_offset);
285 result = send(cl->pfd, mbuf, packetLen, 0);
286 NULLFREE(mbuf);
288 return (result);
291 static int32_t scam_msg_recv(struct s_client *cl, uint8_t *buf, int32_t maxlen)
293 int32_t len;
294 int32_t handle = cl->udp_fd;
295 struct scam_data *scam = cl->scam;
297 if(scam == NULL) { return 0; }
298 if(handle <= 0 || maxlen < 3)
299 { cs_log("scam_msg_recv: fd is 0"); return -1; }
301 len = cs_recv(handle, buf, 2, MSG_WAITALL);
302 if(len != 2) // invalid header length read
304 if(len <= 0)
305 { cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "disconnected by remote server"); }
306 else
307 { cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "invalid header length (expected 2, read %d)", len); }
308 return -1;
311 if(buf[0] != 0x0F)
313 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "invalid packet tag");
314 return 0;
317 int32_t headerSize = buf[1] & 0x80 ? (2 + (buf[1] & ~0x80)) : 2;
318 if(headerSize > 2)
320 if(maxlen < headerSize + 1) { return -1; }
322 len = cs_recv(handle, buf + 2, headerSize - 2, MSG_WAITALL);
323 if(len != headerSize - 2) // invalid header length read
325 if(len <= 0)
326 { cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "disconnected by remote server"); }
327 else
328 { cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "invalid header length (expected %d, read %d)", headerSize, 2+len); }
329 return -1;
333 uint32_t dataLength, dataOffset;
334 scam_decode_length(buf, &dataLength, &dataOffset);
336 if(dataLength) // check if any data is expected in msg
338 if(dataLength % 8 != 0)
340 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "message data has invalid size (size=%d)", dataLength);
341 return 0;
344 if(headerSize + dataLength > (uint32_t)maxlen)
346 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "message too big (size=%d max=%d)", headerSize+dataLength, maxlen);
347 return 0;
350 len = cs_recv(handle, buf + dataOffset, dataLength, MSG_WAITALL);
351 if((uint32_t)len != dataLength)
353 if(len <= 0)
355 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "disconnected by remote");
357 else
359 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "invalid message length read (expected %d, read %d)", dataLength, len);
361 return -1;
364 scam_decrypt_packet(buf, headerSize + dataLength, scam->deckey, dataLength, dataOffset, &scam->dec_xor_offset);
367 return headerSize+dataLength;
370 static int32_t scam_recv(struct s_client *cl, uint8_t *buf, int32_t len)
372 int32_t n;
373 struct s_reader *rdr = (cl->typ == 'c') ? NULL : cl->reader;
375 if(buf == NULL || len <= 0)
376 { return -1; }
378 n = scam_msg_recv(cl, buf, len); // recv and decrypt msg
379 if(n <= 0)
381 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "connection closed by %s, n=%d.", remote_txt(), n);
382 if(rdr)
384 scam_client_close(cl, 1);
386 else
388 cs_disconnect_client(cl);
390 cs_sleepms(150);
391 n = -1;
393 else
395 cl->last = time(NULL); // last client action is now
396 if(rdr) { rdr->last_g = time(NULL); } // last reader receive is now
399 return n;
402 // scam client functions
404 static int32_t scam_client_init(struct s_client *cl);
406 static int32_t scam_client_connect(void)
408 struct s_client *cl = cur_client();
410 if(cl->reader->tcp_connected < 2 && scam_client_init(cl) < 0)
411 { return 0; }
413 if(!cl->udp_fd)
414 { return 0; }
416 return 1;
419 static void scam_client_idle(void)
421 struct s_client *client = cur_client();
422 struct s_reader *rdr = client->reader;
423 time_t now = time(NULL);
424 if(!rdr) { return; }
426 if(rdr->tcp_ito > 0)
428 int32_t time_diff;
429 time_diff = llabs(now - rdr->last_s);
430 if(time_diff > (rdr->tcp_ito))
432 network_tcp_connection_close(rdr, "inactivity");
433 return;
436 else if(rdr->tcp_ito == -1)
438 scam_client_connect();
439 return;
443 static void scam_client_recv_caid(uint8_t *buf, uint32_t len)
445 uint16_t caid;
447 if(len < 3)
449 return;
452 caid = buf[1] << 8 | buf[2];
454 if(buf[0])
456 cs_log("scam server has card: %04X", caid);
458 else
460 cs_log("scam server no longer has card: %04X", caid);
464 static void scam_client_recv_server_version(uint8_t *buf, uint32_t len)
466 uint32_t pos = 0, dataLength = 0, dataOffset = 0, usedLen = 0;
467 char versionString[128];
468 uint16_t versionShort = 0;
469 versionString[0] = 0;
471 scam_decode_length(buf, &dataLength, &dataOffset);
473 while(pos + dataOffset + dataLength - 1 < len)
475 switch(buf[pos])
477 case 0x01: // version string
478 usedLen = dataLength;
479 if(usedLen > 127)
481 usedLen = 127;
483 memcpy(versionString, buf + dataOffset, usedLen);
484 versionString[usedLen] = 0;
485 break;
487 case 0x0A: // version short
488 if(dataLength != 2) break;
489 versionShort = (buf[pos + dataOffset] << 8) | buf[pos + dataOffset + 1];
490 break;
492 default:
493 cs_log_dbg(D_READER, "unknown server version packet tag %X", buf[pos]);
494 break;
497 pos += dataOffset + dataLength;
498 if((pos + 2 < len) && (pos + 1 + scam_get_length_data_length(buf + pos)) < len)
500 scam_decode_length(buf + pos, &dataLength, &dataOffset);
502 else
504 break;
508 cs_log("scam server version: %s (%d)", versionString, versionShort);
511 static void scam_client_recv_dcw(struct s_client *cl, uint8_t *buf, uint32_t len, uint8_t *dcw, int32_t *ecm_task_idx, int32_t *rc)
513 // 00C00000 enigma namespace
514 // 0455 tsid
515 // 0001 onid
516 // 151A srvid
517 // 200081 ???
518 // 943E85577035C469 dcw1
519 // C73882811721E31B dcw2
521 if(len != 29)
523 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "unknown server dcw packet length %d", len);
524 return;
527 *ecm_task_idx = b2i(4, &buf[0]); // we store idx here instead of ens
528 memcpy(dcw, &buf[13], 16);
529 *rc = 1;
532 static void scam_client_send_hello(struct s_client *cl)
534 uint8_t mbuf[70];
535 uint32_t usernameLen, i = 0;
536 struct s_reader *rdr = cl->reader;
537 struct scam_data *scam = cl->scam;
539 if(scam == NULL) { return; }
540 if(!rdr) { return; }
542 usernameLen = strlen(rdr->r_usr);
543 if(usernameLen > 63) // because rdr->r_usr is max. 63+1 chars
545 usernameLen = 63;
548 mbuf[i++] = 0x46; // client hello data type
549 mbuf[i++] = 6 + usernameLen; // will never exceed 63+6 = 69 bytes (<127 bytes)
551 // client version
552 mbuf[i++] = 0xA0; // client version data type
553 mbuf[i++] = 0x02; // data length (2)
554 mbuf[i++] = 0x00; // version ( 0x0007)
555 mbuf[i++] = 0x07;
557 // username
558 mbuf[i++] = 0xA1; // username data type
559 mbuf[i++] = (uint8_t)usernameLen;
560 memcpy(mbuf + i, rdr->r_usr, usernameLen);
561 mbuf[i + usernameLen] = 0;
563 scam_send(cl, mbuf, 8 + usernameLen);
565 scam_generate_deskey(rdr->r_pwd, scam->enckey);
566 scam_generate_deskey(rdr->r_pwd, scam->deckey);
567 scam->enc_xor_offset = 0;
568 scam->dec_xor_offset = 0;
571 static int32_t scam_client_send_ecm(struct s_client *cl, ECM_REQUEST *er)
573 // 2481A5 310A
574 // 00C00000 enigma namespace
575 // 0455 tsid
576 // 0001 onid
577 // 151A srvid
578 // 3002
579 // 1843 caid
580 // 3304
581 // 66A1AE16 pat/pmt crc? we currently fill it with chid
582 // 348189
583 // 8130.. ecm
584 // 3501
585 // 02 needed dcws?
587 uint8_t *mbuf, packetLenData[5], ecmLenData[5];
588 uint32_t i = 0, ret = 0, dataLength = 0, packetLength = 0;
589 uint8_t pLenDataLen = 0, eLenDataLen = 0;
591 if(!scam_client_connect())
592 { return (-1); }
594 scam_encode_length(er->ecmlen, ecmLenData, &eLenDataLen);
595 dataLength = 23 + eLenDataLen + er->ecmlen + 3;
596 scam_encode_length(dataLength, packetLenData, &pLenDataLen);
597 packetLength = 1 + pLenDataLen + dataLength;
599 if(!cs_malloc(&mbuf, packetLength))
600 { return -1; }
602 mbuf[i++] = 0x24; // ecm request data type
603 memcpy(mbuf + i, packetLenData, pLenDataLen); i += pLenDataLen;
605 mbuf[i++] = 0x31; // channel info data type
606 mbuf[i++] = 0x0A; // size is always 0x0A
608 //i2b_buf(4, er->ens, mbuf+i); i += 4;
609 i2b_buf(4, er->idx, mbuf+i); i += 4; // we store idx instead of ens here
611 i2b_buf(2, er->tsid, mbuf + i); i += 2;
612 i2b_buf(2, er->onid, mbuf + i); i += 2;
613 i2b_buf(2, er->srvid, mbuf + i); i += 2;
615 mbuf[i++] = 0x30; // caid data type
616 mbuf[i++] = 0x02; // size is always 0x02
617 i2b_buf(2, er->caid, mbuf + i); i += 2;
619 mbuf[i++] = 0x33; // ??? data type
620 mbuf[i++] = 0x04; // size is always 0x04
621 i2b_buf(2, er->chid, mbuf + i); i += 4;
623 mbuf[i++] = 0x34; // ecm data type
624 memcpy(mbuf + i, ecmLenData, eLenDataLen); i += eLenDataLen;
625 memcpy(mbuf + i, er->ecm, er->ecmlen); i += er->ecmlen;
627 mbuf[i++] = 0x35; // ??? data type
628 mbuf[i++] = 0x01; // size is always 0x01
629 mbuf[i++] = 0x02; // unknown value
631 ret = scam_send(cl, mbuf, packetLength);
633 cs_log_dbg(D_TRACE, "scam: sending ecm");
634 cs_log_dump_dbg(D_CLIENT, mbuf, packetLength, "ecm:");
635 NULLFREE(mbuf);
636 return ((ret < 1) ? (-1) : 0);
639 static int32_t scam_client_init(struct s_client *cl)
641 int32_t handle;
643 handle = network_tcp_connection_open(cl->reader);
644 if(handle < 0) {
645 cl->reader->last_s = 0; // set last send to zero
646 cl->reader->last_g = 0; // set last receive to zero
647 cl->last = 0; // set last client action to zero
648 return (0);
651 if(cl->scam) {
652 memset(cl->scam, 0, sizeof(struct scam_data));
655 if(!cl->scam && !cs_malloc(&cl->scam, sizeof(struct scam_data))) {
656 return 0;
659 cs_log("scam: proxy %s:%d (fd=%d)",
660 cl->reader->device, cl->reader->r_port, cl->udp_fd);
662 cl->reader->tcp_connected = 2;
663 cl->reader->card_status = CARD_INSERTED;
664 cl->reader->last_g = cl->reader->last_s = time((time_t *)0);
666 cs_log_dbg(D_CLIENT, "scam: last_s=%ld, last_g=%ld", cl->reader->last_s, cl->reader->last_g);
668 cl->pfd = cl->udp_fd;
670 scam_client_send_hello(cl);
672 return (0);
675 static int32_t scam_client_handle(struct s_client *cl, uint8_t *dcw, int32_t *rc, uint8_t *buf, int32_t n)
677 uint32_t pos = 0, packetLength = 0, packetOffset = 0, dataLength = 0, dataOffset = 0;
678 int32_t ret = -1;
680 if(n < 3)
682 return (-1);
685 scam_decode_length(buf, &packetLength, &packetOffset);
686 pos += packetOffset;
688 if((pos + 2 < (uint32_t)n) && (pos + 1 + scam_get_length_data_length(buf + pos) < (uint32_t)n))
690 scam_decode_length(buf + pos, &dataLength, &dataOffset);
692 else
694 return (-1);
697 while(pos + dataOffset + dataLength - 1 < (uint32_t)n)
699 switch(buf[pos])
701 case 0x10: // checksum
702 if(dataLength != 2) { break; }
703 if(b2i(2, &buf[pos + dataOffset]) != ccitt_crc(buf + pos + dataOffset + 2, n - pos - dataOffset - 2, 0xFFFF, 0))
705 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "sent packet with invalid checksum");
706 return (-1);
708 break;
710 case 0x20: // caid list
711 scam_client_recv_caid(buf + pos + dataOffset, dataLength);
712 break;
714 case 0x45: // server version
715 scam_client_recv_server_version(buf + pos + dataOffset, dataLength);
716 break;
718 case 0x63: // dcw
719 scam_client_recv_dcw(cl, buf + pos + dataOffset, dataLength, dcw, &ret, rc);
720 break;
722 case 0x7F: // padding
723 break;
725 default:
726 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "unknown scam server packet %X", buf[pos]);
727 break;
730 pos += dataOffset + dataLength;
731 if((pos + 2 < (uint32_t)n) && (pos + 1 + scam_get_length_data_length(buf + pos) < (uint32_t)n))
733 scam_decode_length(buf + pos, &dataLength, &dataOffset);
735 else
737 break;
741 return ret;
744 // scam server functions
745 static uint8_t scam_server_authip_client(struct s_client *cl)
747 if(cfg.scam_allowed && !check_ip(cfg.scam_allowed, cl->ip))
749 cs_log("scam: IP not allowed");
750 cs_auth_client(cl, (struct s_auth *)0, NULL);
751 cs_disconnect_client(cl);
752 return 0;
755 return 1;
758 static void scam_server_init(struct s_client *cl)
760 if(!cl->init_done)
762 if(IP_ISSET(cl->ip))
763 { cs_log("scam: new connection from %s", cs_inet_ntoa(cl->ip)); }
765 if(scam_server_authip_client(cl))
767 if(cl->scam)
769 memset(cl->scam, 0, sizeof(struct scam_data));
772 if(cl->scam || cs_malloc(&cl->scam, sizeof(struct scam_data)))
774 cl->init_done = 1;
778 return;
781 static void scam_server_recv_ecm(struct s_client *cl, uint8_t *buf, int32_t len)
783 uint32_t pos = 0, dataLength = 0, dataOffset = 0, usedLen = 0;
784 ECM_REQUEST *er;
785 uint8_t gotCaid = 0, gotEcm = 0;
787 if(len < 1)
789 return;
792 if(!(er = get_ecmtask()))
793 { return; }
795 scam_decode_length(buf, &dataLength, &dataOffset);
797 while(pos + dataOffset + dataLength - 1 < (uint32_t)len)
799 switch(buf[pos]) {
801 case 0x31: // channel data
802 if(dataLength != 0x0A) break;
803 er->ens = b2i(4, buf + pos + dataOffset);
804 er->tsid = b2i(2, buf + pos + dataOffset + 4);
805 er->onid = b2i(2, buf + pos + dataOffset + 6);
806 er->srvid = b2i(2, buf + pos + dataOffset + 8);
807 break;
809 case 0x30: // caid
810 if(dataLength != 0x02) break;
811 er->caid = b2i(2, buf + pos + dataOffset);
812 gotCaid = 1;
813 break;
815 case 0x33: // unknown
816 break;
818 case 0x34: // ecm
819 usedLen = dataLength;
820 if(usedLen > MAX_ECM_SIZE)
822 break;
824 er->ecmlen = usedLen;
825 memcpy(er->ecm, buf + pos + dataOffset, usedLen);
826 gotEcm = 1;
827 break;
829 case 0x35: // unknown
830 break;
832 default:
833 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "sent unknown scam client ecm tag %X", buf[pos]);
834 break;
837 pos += dataOffset + dataLength;
838 if((pos + 2 < (uint32_t)len) && (pos + 1 + scam_get_length_data_length(buf + pos) < (uint32_t)len))
840 scam_decode_length(buf + pos, &dataLength, &dataOffset);
842 else
844 break;
848 if(gotCaid && gotEcm)
850 get_cw(cl, er);
852 else
854 NULLFREE(er);
855 cs_log("WARNING: ECM-request corrupt");
859 static void scam_caidlist_add(uint16_t *caidlist, uint32_t listsize, uint32_t *count, uint16_t caid)
861 uint32_t i;
862 uint8_t exists = 0;
864 if(*count >= listsize)
866 return;
869 for(i = 0; i < *count; i++)
871 if(caidlist[i] == caid)
873 exists = 1;
874 break;
878 if(!exists)
880 caidlist[*count] = caid;
881 (*count)++;
885 static void scam_server_send_caidlist(struct s_client *cl)
887 uint8_t mbuf[5];
888 int32_t j;
889 uint32_t i = 0;
890 uint16_t caids[55];
891 uint32_t cardcount = 0;
892 struct s_reader *rdr = NULL;
894 cs_readlock(__func__, &readerlist_lock);
895 for(rdr = first_active_reader; rdr; rdr = rdr->next)
897 if(rdr->caid && chk_ctab(rdr->caid, &cl->ctab))
899 scam_caidlist_add(caids, ARRAY_SIZE(caids), &cardcount, rdr->caid);
902 for(j = 0; j < rdr->ctab.ctnum; j++)
904 CAIDTAB_DATA *d = &rdr->ctab.ctdata[j];
905 if(d->caid && chk_ctab(d->caid, &cl->ctab))
907 scam_caidlist_add(caids, ARRAY_SIZE(caids), &cardcount, d->caid);
911 cs_readunlock(__func__, &readerlist_lock);
913 for(j = 0; j < (int32_t)cardcount; j++)
915 i = 0;
916 mbuf[i++] = 0x20; // caid data type
917 mbuf[i++] = 0x03; // length
918 mbuf[i++] = 0x01; // active card
919 i2b_buf(2, caids[j], mbuf + i);
920 scam_send(cl, mbuf, 5);
924 static void scam_server_send_serverversion(struct s_client *cl)
926 uint8_t mbuf[64];
927 uint32_t i = 0;
928 char *version = "scam/3.60 oscam";
929 uint8_t vlen = strlen(version);
931 mbuf[i++] = 0x45; // server version data type
932 mbuf[i++] = 2 + vlen + 4; // will never exceed 127 bytes
934 mbuf[i++] = 0x01; // server version string data type
935 mbuf[i++] = vlen; // will never exceed 127 bytes
936 memcpy(mbuf + i, version, vlen); i += vlen;
938 mbuf[i++] = 0x0A; // server version short data type
939 mbuf[i++] = 0x02; // is always 0x02
940 i2b_buf(2, 0x7, mbuf + i);
942 scam_send(cl, mbuf, 2 + 2 + vlen + 4);
945 static void scam_server_recv_auth(struct s_client *cl, uint8_t *buf, int32_t len)
947 uint32_t pos = 0, dataLength = 0, dataOffset = 0, usedLen = 0;
948 uint8_t userok = 0;
949 struct s_auth *account;
950 struct scam_data *scam = cl->scam;
952 if(scam == NULL) { return; }
953 scam->login_username[0] = 0;
955 if(len < 1)
957 return;
960 scam_decode_length(buf, &dataLength, &dataOffset);
962 while(pos + dataOffset + dataLength - 1 < (uint32_t)len)
964 switch(buf[pos])
966 case 0xA0: // version short
967 if(dataLength != 2) break;
968 scam->version = (buf[pos + dataOffset] << 8) | buf[pos + dataOffset + 1];
969 break;
971 case 0xA1: // username string
972 usedLen = dataLength;
973 if(usedLen > 64) {
974 usedLen = 63;
976 memcpy(scam->login_username, buf + pos + dataOffset, usedLen);
977 scam->login_username[usedLen] = 0;
978 break;
980 default:
981 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "unknown client auth packet tag %X", buf[pos]);
982 break;
985 pos += dataOffset + dataLength;
986 if((pos + 2 < (uint32_t)len) && (pos + 1 + scam_get_length_data_length(buf + pos) < (uint32_t)len))
988 scam_decode_length(buf + pos, &dataLength, &dataOffset);
990 else
992 break;
996 for(account = cfg.account; account; account = account->next)
998 if(streq(scam->login_username, account->usr))
1000 userok = 1;
1001 break;
1005 if(!userok)
1007 cs_auth_client(cl, (struct s_auth *)0, NULL);
1008 cs_disconnect_client(cl);
1009 return;
1012 scam->login_pending = 1;
1013 scam_generate_deskey(account->pwd, scam->enckey);
1014 scam_generate_deskey(account->pwd, scam->deckey);
1015 scam->enc_xor_offset = 0;
1016 scam->dec_xor_offset = 0;
1018 scam_server_send_caidlist(cl);
1019 scam_server_send_serverversion(cl);
1022 static void scam_server_send_dcw(struct s_client *cl, ECM_REQUEST *er)
1024 uint8_t mbuf[31];
1025 uint32_t i = 0;
1027 if(!(er->rc < E_NOTFOUND))
1029 return;
1032 mbuf[i++] = 0x63; // dcw data type
1033 mbuf[i++] = 0x1D; // fixed sized < 127
1035 i2b_buf(4, er->ens, mbuf + i); i += 4;
1036 i2b_buf(2, er->tsid, mbuf + i); i += 2;
1037 i2b_buf(2, er->onid, mbuf + i); i += 2;
1038 i2b_buf(2, er->srvid, mbuf + i); i += 2;
1040 mbuf[i++] = 0x20; // unknown
1041 mbuf[i++] = 0x00; // unknown
1042 mbuf[i++] = 0x81; // unknown
1043 memcpy(mbuf + i, er->cw, 16);
1045 scam_send(cl, mbuf, 31);
1048 static void *scam_server_handle(struct s_client *cl, uint8_t *buf, int32_t n)
1050 uint32_t pos = 0, packetLength = 0, packetOffset = 0, dataLength = 0, dataOffset = 0;
1051 struct s_auth *account;
1052 struct scam_data *scam;
1054 if(n < 3)
1055 { return NULL; }
1057 if(!cl->init_done)
1059 if(!scam_server_authip_client(cl)) { return NULL; }
1061 if(cl->scam)
1063 memset(cl->scam, 0, sizeof(struct scam_data));
1066 if(cl->scam == NULL && !cs_malloc(&cl->scam, sizeof(struct scam_data)))
1068 return NULL;
1070 cl->init_done = 1;
1073 scam = cl->scam;
1074 if(scam == NULL)
1076 return NULL;
1079 scam_decode_length(buf, &packetLength, &packetOffset);
1080 pos += packetOffset;
1082 if(scam->login_pending && packetLength > 1 && (buf[pos] != 0x10 || buf[pos + 1] != 0x02))
1084 scam->login_pending = 0;
1085 cs_auth_client(cl, (struct s_auth *)0, NULL);
1086 cs_disconnect_client(cl);
1087 return NULL;
1090 if((pos + 2 < (uint32_t)n) && (pos + 1 + scam_get_length_data_length(buf + pos) < (uint32_t)n))
1092 scam_decode_length(buf + pos, &dataLength, &dataOffset);
1094 else
1096 return NULL;
1099 while(pos + dataOffset + dataLength - 1 < (uint32_t)n)
1101 switch(buf[pos])
1103 case 0x10: // checksum
1104 if(dataLength != 2) { break; }
1105 if(b2i(2, &buf[pos + dataOffset]) != ccitt_crc(buf + pos + dataOffset + 2, n - pos - dataOffset - 2, 0xFFFF, 0))
1107 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "sent packet with invalid checksum");
1108 return NULL;
1110 if(scam->login_pending)
1112 for(account = cfg.account; account; account = account->next)
1114 if(streq(scam->login_username, account->usr))
1116 scam->login_pending = 0;
1117 if(!cs_auth_client(cl, account, NULL))
1119 cs_log("scam client login: %s version: %d", scam->login_username, scam->version);
1121 else
1123 cs_disconnect_client(cl);
1125 break;
1128 if(scam->login_pending)
1130 scam->login_pending = 0;
1131 cs_auth_client(cl, (struct s_auth *)0, NULL);
1132 cs_disconnect_client(cl);
1133 return NULL;
1136 break;
1138 case 0x46: // client auth
1139 scam_server_recv_auth(cl, buf + pos + dataOffset, dataLength);
1140 break;
1142 case 0x24: // ecm request
1143 scam_server_recv_ecm(cl, buf + pos + dataOffset, dataLength);
1144 break;
1146 case 0x7F: // padding
1147 break;
1149 default:
1150 cs_log_dbg(cl->typ == 'c' ? D_CLIENT : D_READER, "sent unknown scam client packet %X", buf[pos]);
1151 break;
1154 pos += dataOffset + dataLength;
1155 if((pos + 2 < (uint32_t)n) && (pos + 1 + scam_get_length_data_length(buf + pos) < (uint32_t)n))
1157 scam_decode_length(buf + pos, &dataLength, &dataOffset);
1159 else
1161 break;
1165 return NULL;
1168 void scam_cleanup(struct s_client *cl)
1170 NULLFREE(cl->scam);
1173 void module_scam(struct s_module *ph)
1175 ph->desc = "scam";
1176 ph->type = MOD_CONN_TCP;
1177 ph->listenertype = LIS_SCAM;
1178 ph->num = R_SCAM;
1179 ph->large_ecm_support = 1;
1180 IP_ASSIGN(ph->s_ip, cfg.scam_srvip);
1181 ph->ptab.nports = 1;
1182 ph->ptab.ports[0].s_port = cfg.scam_port;
1183 // server + client
1184 ph->recv = scam_recv;
1185 ph->cleanup = scam_cleanup;
1186 // server
1187 ph->s_init = scam_server_init;
1188 ph->s_handler = scam_server_handle;
1189 ph->send_dcw = scam_server_send_dcw;
1190 // client
1191 ph->c_init = scam_client_init;
1192 ph->c_idle = scam_client_idle;
1193 ph->c_recv_chk = scam_client_handle;
1194 ph->c_send_ecm = scam_client_send_ecm;
1197 #endif