⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camd.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 2 页
字号:
    if(caid) CAIDs[numCAIDs++]=caid;    }  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, 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[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>=112) {      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;        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 int 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 + -