📄 camd.c
字号:
} LBSTART(L_CC_LOGIN); LBPUT("%s: CAIDs ",name); for(int i=0; i<numCAIDs && CAIDs[i]; i++) LBPUT("%04X ",CAIDs[i]); LBEND(); return true;}// -- cCardClientCamd35 --------------------------------------------------------struct CmdBlock { unsigned int ucrc; struct { unsigned char cmd; // 0 unsigned char len; // 1 unsigned char pad[2]; // 2 XXXX unsigned int crc; // 4 } udp_header; struct { unsigned short srvID; // 8 unsigned short casID; // 10 unsigned int prvID; // 12 unsigned short pinID; // 16 unsigned char pad2[2];// 18 XXXX } service; unsigned char data[2]; // 20 };#define CBSIZE(cb) (sizeof((cb)->udp_header)+sizeof((cb)->service))#define UCSIZE(cb) (sizeof((cb)->ucrc))#define HDSIZE(cb) (CBSIZE(cb)+UCSIZE(cb))struct EmmReq02 { unsigned short caid; unsigned char hex[4]; unsigned char D0, D2, D3; };struct EmmReq05 { unsigned short caids[8]; // 0 int caidCount; // 16 unsigned char ua[6]; // 20 unsigned short provMap; // 26 struct { // 28 unsigned char prov[2]; unsigned char sa[3]; } provInfo[16]; unsigned char D0, D2, D3; // 108 };class cCardClientCamd35 : public cCardClient, public cAES, private cIdSet {private: unsigned int ucrc; unsigned short pinid; bool exclusive, emmCmd06; cCondVar sleepCond; cTimeMs time;protected: cNetSocket so; bool emmProcessing; char username[33], password[33]; int numCaids, Caids[8]; unsigned char Dx[8]; int lastEmmReq; // virtual bool Login(void); 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);public: cCardClientCamd35(const char *Name); virtual bool Init(const char *config); virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); virtual bool ProcessEMM(int caSys, const unsigned char *data); };static cCardClientLinkReg<cCardClientCamd35> __camd35("Camd35");cCardClientCamd35::cCardClientCamd35(const char *Name):cCardClient(Name),so(DEFAULT_CONNECT_TIMEOUT,CCTIMEOUT/1000,DEFAULT_IDLE_TIMEOUT,true){ emmProcessing=exclusive=emmCmd06=false; pinid=0; numCaids=0; lastEmmReq=0; memset(Dx,0,sizeof(Dx));}bool cCardClientCamd35::ParseUserConfig(const char *config, int *num){ int startNum=*num; if(sscanf(&config[*num],":%32[^:]:%32[^:]%n",username,password,num)==2) { *num+=startNum; ucrc=bswap_32(crc32_le(0,MD5((unsigned char *)username,strlen(username),0),16)); PRINTF(L_CC_CORE,"%s: username=%s password=%s ucrc=%08x",name,username,password,ucrc);; SetKey(MD5((unsigned char *)password,strlen(password),0)); return true; } return false;}bool cCardClientCamd35::SendBlock(struct CmdBlock *cb, int datalen){ 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(&so,buff,l+UCSIZE(cb));}int cCardClientCamd35::RecvBlock(struct CmdBlock *cb, int maxlen, int to){ int n=cCardClient::RecvMsg(&so,(unsigned char *)cb,maxlen,to); if(n<=0) return n; if((unsigned int)n>=CBSIZE(cb)+UCSIZE(cb)) { if(cb->ucrc==ucrc) { Decrypt((unsigned char *)cb+UCSIZE(cb),n-UCSIZE(cb)); if((unsigned int)n<cb->udp_header.len+CBSIZE(cb)+UCSIZE(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::Init(const char *config){ cMutexLock lock(this); so.Disconnect(); int num=0; return (ParseStdConfig(config,&num) && ParseUserConfig(config,&num));}bool cCardClientCamd35::Login(void){ so.Disconnect(); 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;}void cCardClientCamd35::HandleEMMRequest(const struct CmdBlock *cb){ 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; 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; }}bool cCardClientCamd35::CanHandleEMM(unsigned short SysId){ for(int i=numCaids-1; i>=0; i--) if(SysId==Caids[i]) return true; return false;}bool cCardClientCamd35::ProcessEMM(int caSys, const unsigned char *data){ 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) { 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;}bool cCardClientCamd35::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw){ 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); switch(ecm->caId>>8) { case 0x18: n=(data[5]*256)+data[6]; break; default: n=ecm->provId; break; } cb->service.prvID=bswap_32(n); 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) { memcpy(cw,cb->data,16); 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -