|
SASC-NG
DVBSoftCAM
|
Inheritance diagram for cCardClientCamd35:Public Member Functions | |
| cCardClientCamd35 (const char *Name) | |
| virtual bool | Init (const char *config) |
| virtual bool | Login (void) |
| virtual bool | ProcessECM (const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) |
| virtual bool | ProcessEMM (int caSys, const unsigned char *data) |
Protected Member Functions | |
| bool | ParseUserConfig (const char *config, int *num) |
| bool | SendBlock (struct CmdBlock *cb, int datalen) |
| int | RecvBlock (struct CmdBlock *cb, int maxlen, int to) |
| void | HandleEMMRequest (const struct CmdBlock *cb) |
| bool | CanHandleEMM (unsigned short SysId) |
Protected Attributes | |
| bool | emmProcessing |
| char | username [33] |
| char | password [33] |
| int | numCaids |
| int | Caids [8] |
| unsigned char | Dx [8] |
| int | lastEmmReq |
| cCardClientCamd35::cCardClientCamd35 | ( | const char * | Name | ) |
Definition at line 451 of file camd.c.
References CCTIMEOUT, Dx, emmProcessing, lastEmmReq, numCaids, cNetSocket::SetRWTimeout(), cNetSocket::SetUDP(), and cCardClient::so.
:cCardClient(Name) { emmProcessing=exclusive=emmCmd06=false; pinid=0; numCaids=0; lastEmmReq=0; memset(Dx,0,sizeof(Dx)); so.SetRWTimeout(CCTIMEOUT); so.SetUDP(true); }
| bool cCardClientCamd35::CanHandleEMM | ( | unsigned short | SysId | ) | [protected] |
| void cCardClientCamd35::HandleEMMRequest | ( | const struct CmdBlock * | cb | ) | [protected] |
Definition at line 528 of file camd.c.
References cProviders::AddProv(), EmmReq02::caid, EmmReq05::caidCount, EmmReq05::caids, Caids, cCardClient::CaidsChanged(), cIdSet::card, CheckFF(), CheckNull(), CmdBlock::cmd, crc32_le(), EmmReq05::D0, EmmReq02::D0, EmmReq05::D2, EmmReq02::D2, EmmReq05::D3, EmmReq02::D3, CmdBlock::data, Dx, cCardClient::emmAllowed, emmProcessing, EmmReq02::hex, HexStr(), i, L_CC_CAMD35, L_CC_EMM, L_CC_LOGIN, lastEmmReq, LBEND, LBPUT, LBSTARTF, CmdBlock::len, cCardClient::name, numCaids, PRINTF, EmmReq05::prov, EmmReq05::provInfo, EmmReq05::provMap, cIdSet::ResetIdSet(), EmmReq05::sa, cIdSet::SetCard(), EmmReq05::ua, and CmdBlock::udp_header.
Referenced by ProcessECM().
{
int c=crc32_le(0,cb->data,cb->udp_header.len);
if(c!=lastEmmReq) {
lastEmmReq=c;
ResetIdSet();
if(cb->udp_header.cmd==0x02 && cb->udp_header.len>=9) {
struct EmmReq02 *req=(struct EmmReq02 *)cb->data;
numCaids=1;
Caids[0]=bswap_16(req->caid);
SetCard(new cCardIrdeto(req->hex[3],&req->hex[0]));
Dx[0]=req->D0;
Dx[2]=req->D2;
Dx[3]=req->D3;
char str[20];
PRINTF(L_CC_LOGIN,"%s: CAID: %04x HexSerial: %s, HexBase: %02X (D0-%d D2-%d D3-%d)\n",
name,Caids[0],HexStr(str,((cCardIrdeto *)card)->hexSer,3),((cCardIrdeto *)card)->hexBase,
Dx[0],Dx[2],Dx[3]);
if(!emmProcessing || emmCmd06) PRINTF(L_CC_CAMD35,"got cmd 02, doing cmd02 EMM");
emmCmd06=false;
}
else if(cb->udp_header.cmd==0x05 && cb->udp_header.len>=111) {
struct EmmReq05 *req=(struct EmmReq05 *)cb->data;
numCaids=bswap_32(req->caidCount);
for(int i=numCaids-1; i>=0; i--) Caids[i]=bswap_16(req->caids[i]);
LBSTARTF(L_CC_LOGIN);
LBPUT("%s: CAIDS:",name);
for(int i=numCaids-1; i>=0; i--) LBPUT(" %04x",Caids[i]);
char str[20], str2[20];
LBPUT(" ua=%s",HexStr(str,req->ua,6));
switch(Caids[0]>>8) {
case 0x17:
case 0x06: SetCard(new cCardIrdeto(req->ua[3],&req->ua[0])); break;
case 0x01: SetCard(new cCardSeca(&req->ua[0])); break;
case 0x0d: SetCard(new cCardCryptoworks(&req->ua[0])); break;
case 0x05: SetCard(new cCardViaccess(&req->ua[0])); break;
case 0x18: SetCard(new cCardNagra2(&req->ua[2])); break;
default:
LBPUT(" (unhandled)");
break;
}
LBPUT(" providers");
int map=bswap_16(req->provMap);
// for(int i=0; i<15; i++) //XXX not sure what actualy is the correct
// if(map & (1<<i)) { //XXX interpretation of provMap
for(int i=0; i<map && i<15; i++) {
LBPUT(" %d:%s/%s",i,HexStr(str,req->provInfo[i].prov,2),HexStr(str2,req->provInfo[i].sa,3));
if(!CheckNull(req->provInfo[i].sa,3) && !CheckFF(req->provInfo[i].sa,3)) {
switch(Caids[0]>>8) {
case 0x17:
case 0x06: AddProv(new cProviderIrdeto(req->provInfo[i].prov[0],req->provInfo[i].sa)); break;
case 0x01: AddProv(new cProviderSeca(req->provInfo[i].prov,req->provInfo[i].sa)); break;
default:
LBPUT(" <unhandled>");
break;
}
}
}
Dx[0]=req->D0;
Dx[2]=req->D2;
Dx[3]=req->D3;
LBPUT(" (D0-%d D2-%d D3-%d)",Dx[0],Dx[2],Dx[3]);
LBEND();
if(!emmProcessing || !emmCmd06) PRINTF(L_CC_CAMD35,"got cmd 05, doing cmd06 EMM");
emmCmd06=true;
}
else return;
if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
emmProcessing=true;
CaidsChanged();
}
}
| bool cCardClientCamd35::Init | ( | const char * | config | ) | [virtual] |
Implements cCardClient.
Definition at line 510 of file camd.c.
References cCardClient::Logout(), cCardClient::ParseStdConfig(), and ParseUserConfig().
{
cMutexLock lock(this);
Logout();
int num=0;
return (ParseStdConfig(config,&num) && ParseUserConfig(config,&num));
}
| bool cCardClientCamd35::Login | ( | void | ) | [virtual] |
Implements cCardClient.
Definition at line 518 of file camd.c.
References cNetSocket::Connect(), emmProcessing, cCardClient::hostname, L_CC_LOGIN, lastEmmReq, cCardClient::Logout(), cCardClient::name, cCardClient::port, PRINTF, and cCardClient::so.
{
Logout();
if(!so.Connect(hostname,port)) return false;
PRINTF(L_CC_LOGIN,"%s: connected to %s:%d (%s)",name,hostname,port,name);
emmProcessing=false; lastEmmReq=0;
PRINTF(L_CC_LOGIN,"%s: login done",name);
return true;
}
| bool cCardClientCamd35::ParseUserConfig | ( | const char * | config, |
| int * | num | ||
| ) | [protected] |
Definition at line 460 of file camd.c.
References crc32_le(), L_CC_CORE, cCardClient::name, password, PRINTF, cAES::SetKey(), and username.
Referenced by Init().
{
int startNum=*num;
if(sscanf(&config[*num],":%32[^:]:%32[^:]%n",username,password,num)==2) {
*num+=startNum;
unsigned char md[16];
ucrc=bswap_32(crc32_le(0,MD5((unsigned char *)username,strlen(username),md),16));
PRINTF(L_CC_CORE,"%s: username=%s password=%s ucrc=%08x",name,username,password,ucrc);;
SetKey(MD5((unsigned char *)password,strlen(password),md));
return true;
}
return false;
}
| bool cCardClientCamd35::ProcessECM | ( | const cEcmInfo * | ecm, |
| const unsigned char * | data, | ||
| unsigned char * | cw | ||
| ) | [virtual] |
Implements cCardClient.
Definition at line 677 of file camd.c.
References cCondVar::Broadcast(), cEcmInfo::caId, CmdBlock::casID, CCTIMEOUT, CheckNull(), CmdBlock::cmd, CmdBlock::data, HandleEMMRequest(), L_CC_CAMD35, L_CC_ECM, CmdBlock::len, cMutex::Lock(), cCardClient::name, CmdBlock::pinID, cEcmInfo::prgId, PRINTF, cEcmInfo::provId, CmdBlock::prvID, RecvBlock(), SCT_LEN, SendBlock(), CmdBlock::service, cTimeMs::Set(), CmdBlock::srvID, cTimeMs::TimedOut(), cCondVar::TimedWait(), CmdBlock::udp_header, cMutex::Unlock(), and cCondVar::Wait().
{
bool res=false;
const int length=SCT_LEN(data);
if(length<=255) {
Lock();
while(exclusive) sleepCond.Wait(*this);
unsigned char buff[300];
memset(buff,0xff,sizeof(buff));
struct CmdBlock *cb=(struct CmdBlock *)buff;
const unsigned short pid=pinid++;
int n;
while((n=RecvBlock(cb,sizeof(buff),0))>0) {
if(cb->udp_header.cmd==0x01 || cb->udp_header.cmd==0x44)
PRINTF(L_CC_CAMD35,"unexpected CW answer on flush");
else
HandleEMMRequest(cb);
}
cb->udp_header.cmd=0x00;
cb->service.srvID=bswap_16(ecm->prgId);
cb->service.casID=bswap_16(ecm->caId);
cb->service.prvID=bswap_32(ecm->provId);
cb->service.pinID=pid;
memcpy(&cb->data[0],data,length);
if(SendBlock(cb,length)) {
exclusive=true;
time.Set(CCTIMEOUT);
do {
sleepCond.TimedWait(*this,50);
while((n=RecvBlock(cb,sizeof(buff),0))>0) {
if(cb->udp_header.cmd==0x01) {
if(cb->udp_header.len>=16 && cb->service.pinID==pid && !res) {
if(!CheckNull(&cb->data[0],8)) memcpy(&cw[0],&cb->data[0],8);
if(!CheckNull(&cb->data[8],8)) memcpy(&cw[8],&cb->data[8],8);
res=true;
}
else PRINTF(L_CC_CAMD35,"unexpected/bad CW packet");
}
else if(cb->udp_header.cmd==0x44) {
if(cb->service.pinID==pid) {
PRINTF(L_CC_ECM,"%s: server is unable to handle ECM",name);
n=-1;
break;
}
}
else HandleEMMRequest(cb);
}
} while(!res && n>=0 && !time.TimedOut());
if(!res && time.TimedOut()) PRINTF(L_CC_ECM,"%s: CW request timed out",name);
exclusive=false;
sleepCond.Broadcast();
}
Unlock();
}
else PRINTF(L_CC_ECM,"%s: ECM length %d > 255, not supported by UDP protocol",name,length);
return res;
}
| bool cCardClientCamd35::ProcessEMM | ( | int | caSys, |
| const unsigned char * | data | ||
| ) | [virtual] |
Reimplemented from cCardClient.
Definition at line 609 of file camd.c.
References cAssembleData::Assembled(), cMsgCache::Cache(), CanHandleEMM(), CmdBlock::casID, CmdBlock::cmd, CmdBlock::data, Dx, cCardClient::emmAllowed, emmProcessing, cMsgCache::Get(), L_CC_CAMDEXTR, L_CC_EMM, LDUMP, CmdBlock::len, cIdSet::MatchAndAssemble(), cCardClient::msEMM, cCardClient::name, CmdBlock::pinID, PRINTF, cProvider::ProvId(), CmdBlock::prvID, SCT_LEN, SendBlock(), CmdBlock::service, SetSctLen(), CmdBlock::srvID, and CmdBlock::udp_header.
{
if(emmProcessing && emmAllowed) {
cMutexLock lock(this);
PRINTF(L_CC_CAMDEXTR,"got EMM caSys=%.4x",caSys);
if(CanHandleEMM(caSys)) {
LDUMP(L_CC_CAMDEXTR,&data[0],10,"EMM starts with");
int upd;
cProvider *p;
cAssembleData ad(data);
if(MatchAndAssemble(&ad,&upd,&p)) {
PRINTF(L_CC_CAMDEXTR,"EMM matched upd=%d provId=%.4llx",upd,p ? p->ProvId() : 0);
while((data=ad.Assembled())) {
LDUMP(L_CC_CAMDEXTR,&data[0],10,"processing assembled EMM");
if(Dx[upd]) {
unsigned char buff[300];
memset(buff,0xff,sizeof(buff));
struct CmdBlock *cb=(struct CmdBlock *)buff;
cb->udp_header.cmd=emmCmd06 ? 0x06 : 0x02;
cb->service.srvID=0;
cb->service.casID=bswap_16(caSys);
cb->service.prvID=bswap_32(p ? p->ProvId() : 0);
cb->service.pinID=pinid++;
int len=SCT_LEN(data), off=0;
switch(caSys>>8) {
case 0x0d:
{
static const unsigned char head[] = { 0x8F,0x70,0x00,0xA4,0x42,0x00,0x00,0x00 };
int c, n;
switch(data[0]) {
case 0x82: c=0x42; n=10; break;
case 0x84: c=0x48; n=9; break;
case 0x88:
case 0x89: c=0x44; n=5; break;
default: continue;
}
if(len<n) continue;
off=sizeof(head);
memcpy(&cb->data[0],head,off);
cb->data[3+1]=c;
cb->data[3+4]=len-n;
SetSctLen(&cb->data[0],len-n+5);
data+=n; len-=n;
break;
}
}
if(len+off<=255) {
memcpy(&cb->data[off],data,len);
int id=msEMM.Get(&cb->data[0],len+off,0);
if(id>0 || emmAllowed>1) {
SendBlock(cb,len+off);
msEMM.Cache(id,true,0);
}
else PRINTF(L_CC_CAMDEXTR,"not send, already in cache");
}
else PRINTF(L_CC_EMM,"%s: EMM length %d > 255, not supported by UDP protocol",name,len+off);
}
else PRINTF(L_CC_CAMDEXTR,"dropped, updtype %d blocked",upd);
}
return true;
}
else PRINTF(L_CC_CAMDEXTR,"dropped, doesn't match card data");
}
else PRINTF(L_CC_CAMDEXTR,"dropped, doesn't want caSys %.4x",caSys);
}
return false;
}
| int cCardClientCamd35::RecvBlock | ( | struct CmdBlock * | cb, |
| int | maxlen, | ||
| int | to | ||
| ) | [protected] |
Definition at line 487 of file camd.c.
References CmdBlock::crc, crc32_le(), CmdBlock::data, cAES::Decrypt(), HDSIZE, HEXDUMP, L_CC_CAMD35, L_CC_CAMDEXTR, CmdBlock::len, PRINTF, cCardClient::RecvMsg(), CmdBlock::ucrc, UCSIZE, and CmdBlock::udp_header.
Referenced by ProcessECM().
{
unsigned char *m=(unsigned char *)cb;
int n=cCardClient::RecvMsg(m,-maxlen,to);
if(n<=0) return n;
if((unsigned int)n>=HDSIZE(cb)) {
if(cb->ucrc==ucrc) {
Decrypt(m+UCSIZE(cb),n-UCSIZE(cb));
if((unsigned int)n<cb->udp_header.len+HDSIZE(cb))
PRINTF(L_CC_CAMD35,"packet length doesn't match data length");
else if(cb->udp_header.crc!=bswap_32(crc32_le(0,&cb->data[0],cb->udp_header.len)))
PRINTF(L_CC_CAMD35,"data crc failed");
else {
HEXDUMP(L_CC_CAMDEXTR,cb,n,"recv:");
return n;
}
}
else PRINTF(L_CC_CAMD35,"wrong ucrc: got %08x, want %08x",cb->ucrc,ucrc);
}
else PRINTF(L_CC_CAMD35,"short packet received");
return -1;
}
| bool cCardClientCamd35::SendBlock | ( | struct CmdBlock * | cb, |
| int | datalen | ||
| ) | [protected] |
Definition at line 474 of file camd.c.
References AUTOMEM, CBSIZE, CmdBlock::crc, crc32_le(), CmdBlock::data, datalen, cAES::Encrypt(), HEXDUMP, L_CC_CAMDEXTR, CmdBlock::len, cCardClient::SendMsg(), UCSIZE, and CmdBlock::udp_header.
Referenced by ProcessECM(), and ProcessEMM().
{
cb->udp_header.len=datalen;
cb->udp_header.crc=bswap_32(crc32_le(0,&cb->data[0],datalen));
datalen+=CBSIZE(cb);
unsigned char *buff=AUTOMEM(datalen+UCSIZE(cb)+16);
*((unsigned int *)buff)=ucrc;
HEXDUMP(L_CC_CAMDEXTR,cb,datalen+UCSIZE(cb),"send:");
const int l=Encrypt((unsigned char *)cb+UCSIZE(cb),datalen,buff+UCSIZE(cb));
if(l<=0) return false;
return cCardClient::SendMsg(buff,l+UCSIZE(cb));
}
int cCardClientCamd35::Caids[8] [protected] |
Definition at line 432 of file camd.c.
Referenced by CanHandleEMM(), and HandleEMMRequest().
unsigned char cCardClientCamd35::Dx[8] [protected] |
Definition at line 433 of file camd.c.
Referenced by cCardClientCamd35(), HandleEMMRequest(), and ProcessEMM().
bool cCardClientCamd35::emmProcessing [protected] |
Definition at line 430 of file camd.c.
Referenced by cCardClientCamd35(), HandleEMMRequest(), Login(), and ProcessEMM().
int cCardClientCamd35::lastEmmReq [protected] |
Definition at line 434 of file camd.c.
Referenced by cCardClientCamd35(), HandleEMMRequest(), and Login().
int cCardClientCamd35::numCaids [protected] |
Definition at line 432 of file camd.c.
Referenced by CanHandleEMM(), cCardClientCamd35(), and HandleEMMRequest().
char cCardClientCamd35::password[33] [protected] |
Definition at line 431 of file camd.c.
Referenced by ParseUserConfig().
char cCardClientCamd35::username[33] [protected] |
Definition at line 431 of file camd.c.
Referenced by ParseUserConfig().