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
= 0; i
< 16; ++i
)
34 data
[i
] = v1
[i
] ^ v2
[i
];
39 for(i
= 0; i
< 8; ++i
)
41 data
[i
] = v1
[i
] ^ v2
[i
];
46 for(i
= 0; i
< 4; ++i
)
48 data
[i
] = v1
[i
] ^ v2
[i
];
55 *data
++ = *v1
++ ^ *v2
++;
61 static void scam_generate_deskey(char *keyString
, uint8_t *desKey
)
63 uint8_t iv
[8], *tmpKey
;
64 uint32_t i
, passLen
, alignedPassLen
;
65 uint32_t key_schedule
[32];
70 passLen
= keyString
== NULL
? 0 : cs_strlen(keyString
);
75 alignedPassLen
= (passLen
+ 7) & -8;
76 if(alignedPassLen
== 0) alignedPassLen
= 8;
78 if(!cs_malloc(&tmpKey
, alignedPassLen
))
85 memset(tmpKey
, 0xAA, 8);
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
]);
110 static void scam_encrypt_packet(uint8_t *packet
, uint32_t packetLength
, uint8_t *key
, uint32_t dataLength
, uint32_t dataOffset
, uint8_t *xorOffset
)
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];
129 memcpy(tmpKey
, key
, 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
)
148 n
= packet
[1] & ~0x80;
151 for(i
= 0; i
< n
; i
++)
153 *dataLength
= (*dataLength
<< 8) | packet
[2 + i
];
159 *dataLength
= packet
[1];
164 static uint32_t scam_get_length_data_length(uint8_t *packet
)
168 return packet
[1] & ~0x80;
176 static void scam_encode_length(uint32_t len
, uint8_t *data
, uint8_t *dataLen
)
180 data
[0] = (uint8_t)len
;
186 data
[1] = (uint8_t)len
;
192 data
[1] = (uint8_t)(len
>> 8);
193 data
[2] = (uint8_t)(len
& 0xFF);
196 else if(len
< 16777216)
199 data
[1] = (uint8_t)(len
>> 16);
200 data
[2] = (uint8_t)((len
>> 8) & 0xFF);
201 data
[3] = (uint8_t)(len
& 0xFF);
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);
216 static void scam_client_close(struct s_client
*cl
, int32_t call_conclose
)
218 struct s_reader
*rdr
= cl
->reader
;
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"); }
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;
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);
255 else if(paddingLen
> 0 && paddingLen
< 3)
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; }
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
);
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);
291 static int32_t scam_msg_recv(struct s_client
*cl
, uint8_t *buf
, int32_t maxlen
)
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
305 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "disconnected by remote server"); }
307 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid header length (expected 2, read %d)", len
); }
313 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid packet tag");
317 int32_t headerSize
= buf
[1] & 0x80 ? (2 + (buf
[1] & ~0x80)) : 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
326 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "disconnected by remote server"); }
328 { cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid header length (expected %d, read %d)", headerSize
, 2+len
); }
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
);
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
);
350 len
= cs_recv(handle
, buf
+ dataOffset
, dataLength
, MSG_WAITALL
);
351 if((uint32_t)len
!= dataLength
)
355 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "disconnected by remote");
359 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "invalid message length read (expected %d, read %d)", dataLength
, len
);
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
)
373 struct s_reader
*rdr
= (cl
->typ
== 'c') ? NULL
: cl
->reader
;
375 if(buf
== NULL
|| len
<= 0)
378 n
= scam_msg_recv(cl
, buf
, len
); // recv and decrypt msg
381 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "connection closed by %s, n=%d.", remote_txt(), n
);
384 scam_client_close(cl
, 1);
388 cs_disconnect_client(cl
);
395 cl
->last
= time(NULL
); // last client action is now
396 if(rdr
) { rdr
->last_g
= time(NULL
); } // last reader receive is now
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)
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
);
429 time_diff
= llabs(now
- rdr
->last_s
);
430 if(time_diff
> (rdr
->tcp_ito
))
432 network_tcp_connection_close(rdr
, "inactivity");
436 else if(rdr
->tcp_ito
== -1)
438 scam_client_connect();
443 static void scam_client_recv_caid(uint8_t *buf
, uint32_t len
)
452 caid
= buf
[1] << 8 | buf
[2];
456 cs_log("scam server has card: %04X", caid
);
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
)
477 case 0x01: // version string
478 usedLen
= dataLength
;
483 memcpy(versionString
, buf
+ dataOffset
, usedLen
);
484 versionString
[usedLen
] = 0;
487 case 0x0A: // version short
488 if(dataLength
!= 2) break;
489 versionShort
= (buf
[pos
+ dataOffset
] << 8) | buf
[pos
+ dataOffset
+ 1];
493 cs_log_dbg(D_READER
, "unknown server version packet tag %X", buf
[pos
]);
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
);
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
518 // 943E85577035C469 dcw1
519 // C73882811721E31B dcw2
523 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "unknown server dcw packet length %d", len
);
527 *ecm_task_idx
= b2i(4, &buf
[0]); // we store idx here instead of ens
528 memcpy(dcw
, &buf
[13], 16);
532 static void scam_client_send_hello(struct s_client
*cl
)
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; }
542 usernameLen
= cs_strlen(rdr
->r_usr
);
543 if(usernameLen
> 63) // because rdr->r_usr is max. 63+1 chars
548 mbuf
[i
++] = 0x46; // client hello data type
549 mbuf
[i
++] = 6 + usernameLen
; // will never exceed 63+6 = 69 bytes (<127 bytes)
552 mbuf
[i
++] = 0xA0; // client version data type
553 mbuf
[i
++] = 0x02; // data length (2)
554 mbuf
[i
++] = 0x00; // version ( 0x0007)
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
)
574 // 00C00000 enigma namespace
581 // 66A1AE16 pat/pmt crc? we currently fill it with chid
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())
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
))
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:");
636 return ((ret
< 1) ? (-1) : 0);
639 static int32_t scam_client_init(struct s_client
*cl
)
643 handle
= network_tcp_connection_open(cl
->reader
);
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
652 memset(cl
->scam
, 0, sizeof(struct scam_data
));
655 if(!cl
->scam
&& !cs_malloc(&cl
->scam
, sizeof(struct scam_data
))) {
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
);
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;
685 scam_decode_length(buf
, &packetLength
, &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
);
697 while(pos
+ dataOffset
+ dataLength
- 1 < (uint32_t)n
)
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");
710 case 0x20: // caid list
711 scam_client_recv_caid(buf
+ pos
+ dataOffset
, dataLength
);
714 case 0x45: // server version
715 scam_client_recv_server_version(buf
+ pos
+ dataOffset
, dataLength
);
719 scam_client_recv_dcw(cl
, buf
+ pos
+ dataOffset
, dataLength
, dcw
, &ret
, rc
);
722 case 0x7F: // padding
726 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "unknown scam server packet %X", buf
[pos
]);
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
);
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
);
758 static void scam_server_init(struct s_client
*cl
)
763 { cs_log("scam: new connection from %s", cs_inet_ntoa(cl
->ip
)); }
765 if(scam_server_authip_client(cl
))
769 memset(cl
->scam
, 0, sizeof(struct scam_data
));
772 if(cl
->scam
|| cs_malloc(&cl
->scam
, sizeof(struct scam_data
)))
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;
785 uint8_t gotCaid
= 0, gotEcm
= 0;
792 if(!(er
= get_ecmtask()))
795 scam_decode_length(buf
, &dataLength
, &dataOffset
);
797 while(pos
+ dataOffset
+ dataLength
- 1 < (uint32_t)len
)
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);
810 if(dataLength
!= 0x02) break;
811 er
->caid
= b2i(2, buf
+ pos
+ dataOffset
);
815 case 0x33: // unknown
819 usedLen
= dataLength
;
820 if(usedLen
> MAX_ECM_SIZE
)
824 er
->ecmlen
= usedLen
;
825 memcpy(er
->ecm
, buf
+ pos
+ dataOffset
, usedLen
);
829 case 0x35: // unknown
833 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "sent unknown scam client ecm tag %X", buf
[pos
]);
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
);
848 if(gotCaid
&& gotEcm
)
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
)
864 if(*count
>= listsize
)
869 for(i
= 0; i
< *count
; i
++)
871 if(caidlist
[i
] == caid
)
880 caidlist
[*count
] = caid
;
885 static void scam_server_send_caidlist(struct s_client
*cl
)
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
++)
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
)
928 char *version
= "scam/3.60 oscam";
929 uint8_t vlen
= cs_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;
949 struct s_auth
*account
;
950 struct scam_data
*scam
= cl
->scam
;
952 if(scam
== NULL
) { return; }
953 scam
->login_username
[0] = 0;
960 scam_decode_length(buf
, &dataLength
, &dataOffset
);
962 while(pos
+ dataOffset
+ dataLength
- 1 < (uint32_t)len
)
966 case 0xA0: // version short
967 if(dataLength
!= 2) break;
968 scam
->version
= (buf
[pos
+ dataOffset
] << 8) | buf
[pos
+ dataOffset
+ 1];
971 case 0xA1: // username string
972 usedLen
= dataLength
;
976 memcpy(scam
->login_username
, buf
+ pos
+ dataOffset
, usedLen
);
977 scam
->login_username
[usedLen
] = 0;
981 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "unknown client auth packet tag %X", buf
[pos
]);
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
);
996 for(account
= cfg
.account
; account
; account
= account
->next
)
998 if(streq(scam
->login_username
, account
->usr
))
1007 cs_auth_client(cl
, (struct s_auth
*)0, NULL
);
1008 cs_disconnect_client(cl
);
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
)
1027 if(!(er
->rc
< E_NOTFOUND
))
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
;
1059 if(!scam_server_authip_client(cl
)) { return NULL
; }
1063 memset(cl
->scam
, 0, sizeof(struct scam_data
));
1066 if(cl
->scam
== NULL
&& !cs_malloc(&cl
->scam
, sizeof(struct scam_data
)))
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
);
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
);
1099 while(pos
+ dataOffset
+ dataLength
- 1 < (uint32_t)n
)
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");
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
);
1123 cs_disconnect_client(cl
);
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
);
1138 case 0x46: // client auth
1139 scam_server_recv_auth(cl
, buf
+ pos
+ dataOffset
, dataLength
);
1142 case 0x24: // ecm request
1143 scam_server_recv_ecm(cl
, buf
+ pos
+ dataOffset
, dataLength
);
1146 case 0x7F: // padding
1150 cs_log_dbg(cl
->typ
== 'c' ? D_CLIENT
: D_READER
, "sent unknown scam client packet %X", buf
[pos
]);
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
);
1168 void scam_cleanup(struct s_client
*cl
)
1173 void module_scam(struct s_module
*ph
)
1176 ph
->type
= MOD_CONN_TCP
;
1177 ph
->listenertype
= LIS_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
;
1184 ph
->recv
= scam_recv
;
1185 ph
->cleanup
= scam_cleanup
;
1187 ph
->s_init
= scam_server_init
;
1188 ph
->s_handler
= scam_server_handle
;
1189 ph
->send_dcw
= scam_server_send_dcw
;
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
;