1 #define MODULE_LOG_PREFIX "scam"
5 #include "oscam-client.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"
19 uint8_t enc_xor_offset
;
20 uint8_t dec_xor_offset
;
21 uint8_t login_pending
;
22 char login_username
[64];
26 static inline void xxor(uint8_t *data
, int32_t len
, const uint8_t *v1
, const uint8_t *v2
)
32 for(i
= 8; i
< 16; ++i
)
34 data
[i
] = v1
[i
] ^ v2
[i
];
37 for(i
= 4; i
< 8; ++i
)
39 data
[i
] = v1
[i
] ^ v2
[i
];
42 for(i
= 0; i
< 4; ++i
)
44 data
[i
] = v1
[i
] ^ v2
[i
];
48 while(len
--) { *data
++ = *v1
++ ^ *v2
++; }
53 static void scam_generate_deskey(char *keyString
, uint8_t *desKey
)
55 uint8_t iv
[8], *tmpKey
;
56 int32_t i
, passLen
, alignedPassLen
;
57 uint32_t key_schedule
[32];
62 passLen
= keyString
== NULL
? 0 : strlen(keyString
);
67 alignedPassLen
= (passLen
+ 7) & -8;
68 if(alignedPassLen
== 0) alignedPassLen
= 8;
70 if(!cs_malloc(&tmpKey
, alignedPassLen
)) {
75 memset(tmpKey
, 0xAA, 8);
79 memcpy(tmpKey
, keyString
, passLen
);
82 for(i
=0; i
<alignedPassLen
-passLen
; i
++) {
83 tmpKey
[passLen
+i
] = (uint8_t)i
;
86 xxor(desKey
,8,tmpKey
,iv
);
88 for(i
=0; i
<alignedPassLen
; i
+=8) {
89 des_set_key(&tmpKey
[i
], key_schedule
);
90 des(&tmpKey
[i
], key_schedule
, 1);
91 xxor(desKey
,8,desKey
,&tmpKey
[i
]);
97 static void scam_encrypt_packet(uint8_t *packet
, uint32_t packetLength
, uint8_t *key
, uint32_t dataLength
, uint32_t dataOffset
, uint8_t *xorOffset
)
103 des_cbc_encrypt(packet
+ dataOffset
, iv
, key
, dataLength
);
105 for(i
=0; i
<packetLength
; i
++) {
106 key
[*xorOffset
] ^= packet
[i
];
107 *xorOffset
= (*xorOffset
+ 1) & 7;
111 static void scam_decrypt_packet(uint8_t *packet
, uint32_t packetLength
, uint8_t *key
, uint32_t dataLength
, uint32_t dataOffset
, uint8_t *xorOffset
)
113 uint8_t tmpKey
[8], iv
[8];
115 memcpy(tmpKey
, key
, 8);
118 for(i
=0; i
<packetLength
; i
++) {
119 tmpKey
[*xorOffset
] ^= packet
[i
];
120 *xorOffset
= (*xorOffset
+ 1) & 7;
123 des_cbc_decrypt(packet
+ dataOffset
, iv
, key
, dataLength
);
124 memcpy(key
, tmpKey
, 8);
127 static void scam_decode_length(uint8_t *packet
, uint32_t *dataLength
, uint32_t *dataOffset
)
131 if(packet
[1] & 0x80) {
135 *dataLength
= (*dataLength
<< 8) | packet
[2+i
];
140 *dataLength
= packet
[1];
145 static uint32_t scam_get_length_data_length(uint8_t *packet
)
147 if(packet
[1] & 0x80) {
148 return packet
[1]&~0x80;
155 static void scam_encode_length(uint32_t len
, uint8_t *data
, uint8_t *dataLen
)
159 data
[0] = (uint8_t)len
;
165 data
[1] = (uint8_t)len
;
168 else if (len
< 65536 ) {
170 data
[1] = (uint8_t)(len
>>8);
171 data
[2] = (uint8_t)(len
&0xFF);
174 else if (len
< 16777216 )
177 data
[1] = (uint8_t)(len
>>16);
178 data
[2] = (uint8_t)((len
>>8)&0xFF);
179 data
[3] = (uint8_t)(len
&0xFF);
185 data
[1] = (uint8_t)(len
>>24);
186 data
[2] = (uint8_t)((len
>>16)&0xFF);
187 data
[3] = (uint8_t)((len
>>8)&0xFF);
188 data
[4] = (uint8_t)(len
&0xFF);
194 static void scam_client_close(struct s_client
*cl
, int32_t call_conclose
)
196 struct s_reader
*rdr
= cl
->reader
;
199 if(rdr
) { rdr
->tcp_connected
= 0; }
200 if(rdr
) { rdr
->card_status
= NO_CARD
; }
201 if(rdr
) { rdr
->last_s
= rdr
->last_g
= 0; }
202 if(cl
) { cl
->last
= 0; }
204 if(call_conclose
) //clears also pending ecms!
205 { network_tcp_connection_close(rdr
, "close"); }
217 static int32_t scam_send(struct s_client
*cl
, uchar
*buf
, uint32_t len
)
219 uchar
*mbuf
, lenData
[5];
220 uint8_t lenDataLen
= 0, paddingLen
= 0;
222 int32_t result
, packetLen
;
223 struct scam_data
*scam
= cl
->scam
;
225 if(scam
== NULL
) { return 0; }
226 if(len
== 0) { return 0; }
228 paddingLen
= 8 - ((4+len
) % 8);
229 if(paddingLen
== 8) {
232 else if(paddingLen
> 0 && paddingLen
< 3) {
236 scam_encode_length(4+len
+paddingLen
, lenData
, &lenDataLen
);
237 if(lenDataLen
== 0) { return -1; }
238 packetLen
= 1+lenDataLen
+4+len
+paddingLen
;
239 if(!cs_malloc(&mbuf
, packetLen
)) { return -1; }
242 memcpy(&mbuf
[1], lenData
, lenDataLen
);
243 mbuf
[1+lenDataLen
] = 0x10;
244 mbuf
[1+lenDataLen
+1] = 0x02;
245 memcpy(&mbuf
[1+lenDataLen
+4], buf
, len
);
248 mbuf
[1+lenDataLen
+4+len
] = 0x7F;
249 mbuf
[1+lenDataLen
+4+len
+1] = paddingLen
- 2;
250 get_random_bytes(mbuf
+1+lenDataLen
+4+len
+2, paddingLen
- 2);
253 crc
= ccitt_crc(mbuf
+1+lenDataLen
+4, len
+paddingLen
, 0xFFFF, 0);
254 i2b_buf(2, crc
, &mbuf
[1+lenDataLen
+2]);
256 scam_encrypt_packet(mbuf
, packetLen
, scam
->enckey
, 4+len
+paddingLen
, 1+lenDataLen
, &scam
->enc_xor_offset
);
257 result
= send(cl
->pfd
, mbuf
, packetLen
, 0);
263 static int32_t scam_msg_recv(struct s_client
*cl
, uint8_t *buf
, int32_t maxlen
)
266 int32_t handle
= cl
->udp_fd
;
267 struct scam_data
*scam
= cl
->scam
;
269 if(scam
== NULL
) { return 0; }
270 if(handle
<= 0 || maxlen
< 3)
271 { cs_log("scam_msg_recv: fd is 0"); return -1; }
273 len
= cs_recv(handle
, buf
, 2, MSG_WAITALL
);
274 if(len
!= 2) // invalid header length read
277 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "disconnected by remote server"); }
279 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid header length (expected 2, read %d)", len
); }
285 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid packet tag");
289 int32_t headerSize
= buf
[1]&0x80 ? (2 + (buf
[1]&~0x80)) : 2;
291 if(maxlen
< headerSize
+1) { return -1; }
292 len
= cs_recv(handle
, buf
+2, headerSize
-2, MSG_WAITALL
);
293 if(len
!= headerSize
-2) // invalid header length read
296 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "disconnected by remote server"); }
298 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid header length (expected %d, read %d)", headerSize
, 2+len
); }
303 uint32_t dataLength
, dataOffset
;
304 scam_decode_length(buf
, &dataLength
, &dataOffset
);
306 if(dataLength
) // check if any data is expected in msg
308 if(dataLength
%8 != 0)
310 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "message data has invalid size (size=%d)", dataLength
);
314 if(headerSize
+dataLength
> (uint32_t)maxlen
)
316 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "message too big (size=%d max=%d)", headerSize
+dataLength
, maxlen
);
320 len
= cs_recv(handle
, buf
+ dataOffset
, dataLength
, MSG_WAITALL
);
321 if((uint32_t)len
!= dataLength
)
324 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "disconnected by remote");
327 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid message length read (expected %d, read %d)", dataLength
, len
);
332 scam_decrypt_packet(buf
, headerSize
+dataLength
, scam
->deckey
, dataLength
, dataOffset
, &scam
->dec_xor_offset
);
335 return headerSize
+dataLength
;
338 static int32_t scam_recv(struct s_client
*cl
, uchar
*buf
, int32_t len
)
341 struct s_reader
*rdr
= (cl
->typ
== 'c') ? NULL
: cl
->reader
;
343 if(buf
== NULL
|| len
<= 0)
346 n
= scam_msg_recv(cl
, buf
, len
); // recv and decrypt msg
349 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "connection closed by %s, n=%d.", remote_txt(), n
);
352 scam_client_close(cl
, 1);
356 cs_disconnect_client(cl
);
363 cl
->last
= time(NULL
); // last client action is now
364 if(rdr
) { rdr
->last_g
= time(NULL
); } // last reader receive is now
370 //scam client functions
372 static int32_t scam_client_init(struct s_client
*cl
);
374 static int32_t scam_client_connect(void)
376 struct s_client
*cl
= cur_client();
378 if(cl
->reader
->tcp_connected
< 2 && scam_client_init(cl
) < 0)
387 static void scam_client_idle(void)
389 struct s_client
*client
= cur_client();
390 struct s_reader
*rdr
= client
->reader
;
391 time_t now
= time(NULL
);
397 time_diff
= llabs(now
- rdr
->last_s
);
398 if(time_diff
> (rdr
->tcp_ito
))
400 network_tcp_connection_close(rdr
, "inactivity");
404 else if(rdr
->tcp_ito
== -1)
406 scam_client_connect();
411 static void scam_client_recv_caid(uint8_t *buf
, uint32_t len
)
419 caid
= buf
[1] << 8 | buf
[2];
421 cs_log("scam server has card: %04X", caid
);
424 cs_log("scam server no longer has card: %04X", caid
);
428 static void scam_client_recv_server_version(uint8_t *buf
, uint32_t len
)
430 uint32_t pos
= 0, dataLength
= 0, dataOffset
= 0, usedLen
= 0;
431 char versionString
[128];
432 uint16_t versionShort
= 0;
433 versionString
[0] = 0;
435 scam_decode_length(buf
, &dataLength
, &dataOffset
);
437 while(pos
+dataOffset
+dataLength
-1 < len
)
441 case 0x01: // version string
442 usedLen
= dataLength
;
446 memcpy(versionString
, buf
+dataOffset
, usedLen
);
447 versionString
[usedLen
] = 0;
450 case 0x0A: // version short
451 if(dataLength
!= 2) break;
452 versionShort
= (buf
[pos
+dataOffset
] << 8) | buf
[pos
+dataOffset
+1];
456 cs_log_dbg(D_READER
, "unknown server version packet tag %X", buf
[pos
]);
460 pos
+= dataOffset
+dataLength
;
461 if(pos
+2 < len
&& pos
+1+scam_get_length_data_length(buf
+pos
) < len
) {
462 scam_decode_length(buf
+pos
, &dataLength
, &dataOffset
);
469 cs_log("scam server version: %s (%d)", versionString
, versionShort
);
472 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
)
474 // 00C00000 enimga namespace
479 // 943E85577035C469 dcw1
480 // C73882811721E31B dcw2
483 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "unknown server dcw packet length %d", len
);
487 *ecm_task_idx
= b2i(4, &buf
[0]); // we store idx here instead of ens
488 memcpy(dcw
, &buf
[13], 16);
492 static void scam_client_send_hello(struct s_client
*cl
)
495 uint32_t usernameLen
, i
= 0;
496 struct s_reader
*rdr
= cl
->reader
;
497 struct scam_data
*scam
= cl
->scam
;
499 if(scam
== NULL
) { return; }
502 usernameLen
= strlen(rdr
->r_usr
);
503 if(usernameLen
> 63) { // because rdr->r_usr is max. 63+1 chars
507 mbuf
[i
++] = 0x46; // client hello data type
508 mbuf
[i
++] = 6 + usernameLen
; // will never exceed 63+6 = 69 bytes (<127 bytes)
511 mbuf
[i
++] = 0xA0; // client version data type
512 mbuf
[i
++] = 0x02; // data length (2)
513 mbuf
[i
++] = 0x00; // version ( 0x0007)
517 mbuf
[i
++] = 0xA1; // username data type
518 mbuf
[i
++] = (uint8_t)usernameLen
;
519 memcpy(mbuf
+i
, rdr
->r_usr
, usernameLen
);
520 mbuf
[i
+usernameLen
] = 0;
522 scam_send(cl
, mbuf
, 8+usernameLen
);
524 scam_generate_deskey(rdr
->r_pwd
, scam
->enckey
);
525 scam_generate_deskey(rdr
->r_pwd
, scam
->deckey
);
526 scam
->enc_xor_offset
= 0;
527 scam
->dec_xor_offset
= 0;
530 static int32_t scam_client_send_ecm(struct s_client
*cl
, ECM_REQUEST
*er
)
533 // 00C00000 enimga namespace
540 // 66A1AE16 pat/pmt crc? we currently fill it with chid
546 uchar
*mbuf
, packetLenData
[5], ecmLenData
[5];
547 uint32_t i
= 0, ret
= 0, dataLength
= 0, packetLength
= 0;
548 uint8_t pLenDataLen
= 0, eLenDataLen
= 0;
550 if(!scam_client_connect())
553 scam_encode_length(er
->ecmlen
, ecmLenData
, &eLenDataLen
);
554 dataLength
= 23 + eLenDataLen
+ er
->ecmlen
+ 3;
555 scam_encode_length(dataLength
, packetLenData
, &pLenDataLen
);
556 packetLength
= 1 + pLenDataLen
+ dataLength
;
558 if(!cs_malloc(&mbuf
, packetLength
))
561 mbuf
[i
++] = 0x24; // ecm request data type
562 memcpy(mbuf
+i
, packetLenData
, pLenDataLen
); i
+= pLenDataLen
;
564 mbuf
[i
++] = 0x31; // channel info data type
565 mbuf
[i
++] = 0x0A; // size is always 0x0A
567 //i2b_buf(4, er->ens, mbuf+i); i += 4;
568 i2b_buf(4, er
->idx
, mbuf
+i
); i
+= 4; // we store idx instead of ens here
570 i2b_buf(2, er
->tsid
, mbuf
+i
); i
+= 2;
571 i2b_buf(2, er
->onid
, mbuf
+i
); i
+= 2;
572 i2b_buf(2, er
->srvid
, mbuf
+i
); i
+= 2;
574 mbuf
[i
++] = 0x30; // caid data type
575 mbuf
[i
++] = 0x02; // size is always 0x02
576 i2b_buf(2, er
->caid
, mbuf
+i
); i
+= 2;
578 mbuf
[i
++] = 0x33; // ??? data type
579 mbuf
[i
++] = 0x04; // size is always 0x04
580 i2b_buf(2, er
->chid
, mbuf
+i
); i
+= 4;
582 mbuf
[i
++] = 0x34; // ecm data type
583 memcpy(mbuf
+i
, ecmLenData
, eLenDataLen
); i
+= eLenDataLen
;
584 memcpy(mbuf
+i
, er
->ecm
, er
->ecmlen
); i
+= er
->ecmlen
;
586 mbuf
[i
++] = 0x35; // ??? data type
587 mbuf
[i
++] = 0x01; // size is always 0x01
588 mbuf
[i
++] = 0x02; // unknown value
590 ret
= scam_send(cl
, mbuf
, packetLength
);
592 cs_log_dbg(D_TRACE
, "scam: sending ecm");
593 cs_log_dump_dbg(D_CLIENT
, mbuf
, packetLength
, "ecm:");
595 return ((ret
< 1) ? (-1) : 0);
598 static int32_t scam_client_init(struct s_client
*cl
)
602 handle
= network_tcp_connection_open(cl
->reader
);
604 cl
->reader
->last_s
= 0; // set last send to zero
605 cl
->reader
->last_g
= 0; // set last receive to zero
606 cl
->last
= 0; // set last client action to zero
611 memset(cl
->scam
, 0, sizeof(struct scam_data
));
614 if(!cl
->scam
&& !cs_malloc(&cl
->scam
, sizeof(struct scam_data
))) {
618 cs_log("scam: proxy %s:%d (fd=%d)",
619 cl
->reader
->device
, cl
->reader
->r_port
, cl
->udp_fd
);
621 cl
->reader
->tcp_connected
= 2;
622 cl
->reader
->card_status
= CARD_INSERTED
;
623 cl
->reader
->last_g
= cl
->reader
->last_s
= time((time_t *)0);
625 cs_log_dbg(D_CLIENT
, "scam: last_s=%ld, last_g=%ld", cl
->reader
->last_s
, cl
->reader
->last_g
);
627 cl
->pfd
= cl
->udp_fd
;
629 scam_client_send_hello(cl
);
634 static int32_t scam_client_handle(struct s_client
*cl
, uchar
*dcw
, int32_t *rc
, uchar
*buf
, int32_t n
)
636 uint32_t pos
= 0, packetLength
= 0, packetOffset
= 0, dataLength
= 0, dataOffset
= 0;
643 scam_decode_length(buf
, &packetLength
, &packetOffset
);
646 if(pos
+2 < (uint32_t)n
&& pos
+1+scam_get_length_data_length(buf
+pos
) < (uint32_t)n
) {
647 scam_decode_length(buf
+pos
, &dataLength
, &dataOffset
);
653 while(pos
+dataOffset
+dataLength
-1 < (uint32_t)n
)
656 case 0x10: // checksum
657 if(dataLength
!= 2) { break; }
658 if(b2i(2, &buf
[pos
+dataOffset
]) != ccitt_crc(buf
+pos
+dataOffset
+2, n
-pos
-dataOffset
-2, 0xFFFF, 0)) {
659 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "sent packet with invalid checksum");
664 case 0x20: // caid list
665 scam_client_recv_caid(buf
+pos
+dataOffset
, dataLength
);
668 case 0x45: // server version
669 scam_client_recv_server_version(buf
+pos
+dataOffset
, dataLength
);
673 scam_client_recv_dcw(cl
, buf
+pos
+dataOffset
, dataLength
, dcw
, &ret
, rc
);
676 case 0x7F: // padding
680 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "unknown scam server packet %X", buf
[pos
]);
684 pos
+= dataOffset
+dataLength
;
685 if(pos
+2 < (uint32_t)n
&& pos
+1+scam_get_length_data_length(buf
+pos
) < (uint32_t)n
) {
686 scam_decode_length(buf
+pos
, &dataLength
, &dataOffset
);
696 // scam server functions
697 static uint8_t scam_server_authip_client(struct s_client
*cl
)
699 if(cfg
.scam_allowed
&& !check_ip(cfg
.scam_allowed
, cl
->ip
))
701 cs_log("scam: IP not allowed");
702 cs_auth_client(cl
, (struct s_auth
*)0, NULL
);
703 cs_disconnect_client(cl
);
710 static void scam_server_init(struct s_client
*cl
)
715 { cs_log("scam: new connection from %s", cs_inet_ntoa(cl
->ip
)); }
717 if(scam_server_authip_client(cl
)) {
719 memset(cl
->scam
, 0, sizeof(struct scam_data
));
721 if(cl
->scam
|| cs_malloc(&cl
->scam
, sizeof(struct scam_data
))) {
729 static void scam_server_recv_ecm(struct s_client
*cl
, uchar
*buf
, int32_t len
)
731 uint32_t pos
= 0, dataLength
= 0, dataOffset
= 0, usedLen
= 0;
733 uint8_t gotCaid
= 0, gotEcm
= 0;
739 if(!(er
= get_ecmtask()))
742 scam_decode_length(buf
, &dataLength
, &dataOffset
);
744 while(pos
+dataOffset
+dataLength
-1 < (uint32_t)len
)
748 case 0x31: // channel data
749 if(dataLength
!= 0x0A) break;
750 er
->ens
= b2i(4, buf
+pos
+dataOffset
);
751 er
->tsid
= b2i(2, buf
+pos
+dataOffset
+4);
752 er
->onid
= b2i(2, buf
+pos
+dataOffset
+6);
753 er
->srvid
= b2i(2, buf
+pos
+dataOffset
+8);
757 if(dataLength
!= 0x02) break;
758 er
->caid
= b2i(2, buf
+pos
+dataOffset
);
762 case 0x33: // unknown
766 usedLen
= dataLength
;
767 if(usedLen
> MAX_ECM_SIZE
) {
770 er
->ecmlen
= usedLen
;
771 memcpy(er
->ecm
, buf
+pos
+dataOffset
, usedLen
);
775 case 0x35: // unknown
779 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "sent unknown scam client ecm tag %X", buf
[pos
]);
783 pos
+= dataOffset
+dataLength
;
784 if(pos
+2 < (uint32_t)len
&& pos
+1+scam_get_length_data_length(buf
+pos
) < (uint32_t)len
) {
785 scam_decode_length(buf
+pos
, &dataLength
, &dataOffset
);
792 if(gotCaid
&& gotEcm
) {
797 cs_log("WARNING: ECM-request corrupt");
801 static void scam_caidlist_add(uint16_t *caidlist
, uint32_t listsize
, uint32_t *count
, uint16_t caid
)
806 if(*count
>= listsize
) {
810 for(i
=0; i
<*count
; i
++) {
811 if(caidlist
[i
] == caid
) {
818 caidlist
[*count
] = caid
;
823 static void scam_server_send_caidlist(struct s_client
*cl
)
829 uint32_t cardcount
= 0;
830 struct s_reader
*rdr
= NULL
;
832 cs_readlock(__func__
, &readerlist_lock
);
833 for(rdr
= first_active_reader
; rdr
; rdr
= rdr
->next
)
835 if(rdr
->caid
&& chk_ctab(rdr
->caid
, &cl
->ctab
)) {
836 scam_caidlist_add(caids
, ARRAY_SIZE(caids
), &cardcount
, rdr
->caid
);
839 for(j
= 0; j
< rdr
->ctab
.ctnum
; j
++) {
840 CAIDTAB_DATA
*d
= &rdr
->ctab
.ctdata
[j
];
841 if(d
->caid
&& chk_ctab(d
->caid
, &cl
->ctab
)) {
842 scam_caidlist_add(caids
, ARRAY_SIZE(caids
), &cardcount
, d
->caid
);
846 cs_readunlock(__func__
, &readerlist_lock
);
848 for(j
=0; j
< (int32_t)cardcount
; j
++) {
850 mbuf
[i
++] = 0x20; // caid data type
851 mbuf
[i
++] = 0x03; // length
852 mbuf
[i
++] = 0x01; // active card
853 i2b_buf(2, caids
[j
], mbuf
+i
);
854 scam_send(cl
, mbuf
, 5);
858 static void scam_server_send_serverversion(struct s_client
*cl
)
862 char *version
= "scam/3.60 oscam";
863 uint8_t vlen
= strlen(version
);
865 mbuf
[i
++] = 0x45; // server version data type
866 mbuf
[i
++] = 2+vlen
+4; // will never exceed 127 bytes
868 mbuf
[i
++] = 0x01; // server version string data type
869 mbuf
[i
++] = vlen
; // will never exceed 127 bytes
870 memcpy(mbuf
+i
, version
, vlen
); i
+= vlen
;
872 mbuf
[i
++] = 0x0A; // server version short data type
873 mbuf
[i
++] = 0x02; // is always 0x02
874 i2b_buf(2, 0x7, mbuf
+i
);
876 scam_send(cl
, mbuf
, 2+2+vlen
+4);
879 static void scam_server_recv_auth(struct s_client
*cl
, uchar
*buf
, int32_t len
)
881 uint32_t pos
= 0, dataLength
= 0, dataOffset
= 0, usedLen
= 0;
883 struct s_auth
*account
;
884 struct scam_data
*scam
= cl
->scam
;
886 if(scam
== NULL
) { return; }
887 scam
->login_username
[0] = 0;
893 scam_decode_length(buf
, &dataLength
, &dataOffset
);
895 while(pos
+dataOffset
+dataLength
-1 < (uint32_t)len
)
899 case 0xA0: // version short
900 if(dataLength
!= 2) break;
901 scam
->version
= (buf
[pos
+dataOffset
] << 8) | buf
[pos
+dataOffset
+1];
904 case 0xA1: // username string
905 usedLen
= dataLength
;
909 memcpy(scam
->login_username
, buf
+pos
+dataOffset
, usedLen
);
910 scam
->login_username
[usedLen
] = 0;
914 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "unknown client auth packet tag %X", buf
[pos
]);
918 pos
+= dataOffset
+dataLength
;
919 if(pos
+2 < (uint32_t)len
&& pos
+1+scam_get_length_data_length(buf
+pos
) < (uint32_t)len
) {
920 scam_decode_length(buf
+pos
, &dataLength
, &dataOffset
);
927 for(account
= cfg
.account
; account
; account
= account
->next
)
929 if(streq(scam
->login_username
, account
->usr
))
938 cs_auth_client(cl
, (struct s_auth
*)0, NULL
);
939 cs_disconnect_client(cl
);
943 scam
->login_pending
= 1;
944 scam_generate_deskey(account
->pwd
, scam
->enckey
);
945 scam_generate_deskey(account
->pwd
, scam
->deckey
);
946 scam
->enc_xor_offset
= 0;
947 scam
->dec_xor_offset
= 0;
949 scam_server_send_caidlist(cl
);
950 scam_server_send_serverversion(cl
);
953 static void scam_server_send_dcw(struct s_client
*cl
, ECM_REQUEST
*er
)
958 if(!(er
->rc
< E_NOTFOUND
)) {
962 mbuf
[i
++] = 0x63; // dcw data type
963 mbuf
[i
++] = 0x1D; // fixed sized < 127
965 i2b_buf(4, er
->ens
, mbuf
+i
); i
+= 4;
966 i2b_buf(2, er
->tsid
, mbuf
+i
); i
+= 2;
967 i2b_buf(2, er
->onid
, mbuf
+i
); i
+= 2;
968 i2b_buf(2, er
->srvid
, mbuf
+i
); i
+= 2;
970 mbuf
[i
++] = 0x20; // unknown
971 mbuf
[i
++] = 0x00; // unknown
972 mbuf
[i
++] = 0x81; // unknown
973 memcpy(mbuf
+i
, er
->cw
, 16);
975 scam_send(cl
, mbuf
, 31);
978 static void *scam_server_handle(struct s_client
*cl
, uchar
*buf
, int32_t n
)
980 uint32_t pos
= 0, packetLength
= 0, packetOffset
= 0, dataLength
= 0, dataOffset
= 0;
981 struct s_auth
*account
;
982 struct scam_data
*scam
;
989 if(!scam_server_authip_client(cl
)) { return NULL
; }
991 memset(cl
->scam
, 0, sizeof(struct scam_data
));
993 if(cl
->scam
== NULL
&& !cs_malloc(&cl
->scam
, sizeof(struct scam_data
))) {
1004 scam_decode_length(buf
, &packetLength
, &packetOffset
);
1005 pos
+= packetOffset
;
1007 if(scam
->login_pending
&& packetLength
> 1 && (buf
[pos
] != 0x10 || buf
[pos
+1] != 0x02)) {
1008 scam
->login_pending
= 0;
1009 cs_auth_client(cl
, (struct s_auth
*)0, NULL
);
1010 cs_disconnect_client(cl
);
1014 if(pos
+2 < (uint32_t)n
&& pos
+1+scam_get_length_data_length(buf
+pos
) < (uint32_t)n
) {
1015 scam_decode_length(buf
+pos
, &dataLength
, &dataOffset
);
1021 while(pos
+dataOffset
+dataLength
-1 < (uint32_t)n
)
1025 case 0x10: // checksum
1026 if(dataLength
!= 2) { break; }
1027 if(b2i(2, &buf
[pos
+dataOffset
]) != ccitt_crc(buf
+pos
+dataOffset
+2, n
-pos
-dataOffset
-2, 0xFFFF, 0)) {
1028 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "sent packet with invalid checksum");
1031 if(scam
->login_pending
) {
1032 for(account
= cfg
.account
; account
; account
= account
->next
) {
1033 if(streq(scam
->login_username
, account
->usr
)) {
1034 scam
->login_pending
= 0;
1035 if(!cs_auth_client(cl
, account
, NULL
)) {
1036 cs_log("scam client login: %s version: %d", scam
->login_username
, scam
->version
);
1039 cs_disconnect_client(cl
);
1044 if(scam
->login_pending
)
1046 scam
->login_pending
= 0;
1047 cs_auth_client(cl
, (struct s_auth
*)0, NULL
);
1048 cs_disconnect_client(cl
);
1054 case 0x46: // client auth
1055 scam_server_recv_auth(cl
, buf
+pos
+dataOffset
, dataLength
);
1058 case 0x24: // ecm request
1059 scam_server_recv_ecm(cl
, buf
+pos
+dataOffset
, dataLength
);
1062 case 0x7F: // padding
1066 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "sent unknown scam client packet %X", buf
[pos
]);
1070 pos
+= dataOffset
+dataLength
;
1071 if(pos
+2 < (uint32_t)n
&& pos
+1+scam_get_length_data_length(buf
+pos
) < (uint32_t)n
) {
1072 scam_decode_length(buf
+pos
, &dataLength
, &dataOffset
);
1082 void scam_cleanup(struct s_client
*cl
)
1087 void module_scam(struct s_module
*ph
)
1090 ph
->type
= MOD_CONN_TCP
;
1091 ph
->listenertype
= LIS_SCAM
;
1093 ph
->large_ecm_support
= 1;
1094 IP_ASSIGN(ph
->s_ip
, cfg
.scam_srvip
);
1095 ph
->ptab
.nports
= 1;
1096 ph
->ptab
.ports
[0].s_port
= cfg
.scam_port
;
1098 ph
->recv
= scam_recv
;
1099 ph
->cleanup
= scam_cleanup
;
1101 ph
->s_init
= scam_server_init
;
1102 ph
->s_handler
= scam_server_handle
;
1103 ph
->send_dcw
= scam_server_send_dcw
;
1105 ph
->c_init
= scam_client_init
;
1106 ph
->c_idle
= scam_client_idle
;
1107 ph
->c_recv_chk
= scam_client_handle
;
1108 ph
->c_send_ecm
= scam_client_send_ecm
;