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

📄 camd.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Softcam plugin to VDR (C++) * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */#include <stdio.h>#include <string.h>#include <byteswap.h>#include "cc.h"#include "network.h"#include "crypto.h"#include "misc.h"#include "parse.h"#include <openssl/md5.h>#define CCVERSION "3.37"#define CCTIMEOUT 5000 // ms// -- cCardClientCommon --------------------------------------------------------class cCardClientCommon : public cCardClient, public cAES, protected cIdSet {private:  bool conReply, logReply, doAES;  bool exclusive;  int minMsgLen;  cCondVar sleepCond;  cTimeMs time;protected:  cNetSocket so;  bool emmProcessing;  char username[11], password[11];  //  virtual bool Login(void);  bool ParseKeyConfig(const char *config, int *num);  bool ParseUserConfig(const char *config, int *num);  virtual bool SendMsg(cNetSocket *so, const unsigned char *data, int len);  virtual int RecvMsg(cNetSocket *so, unsigned char *data, int len, int to=-1);  virtual void HandleEMMRequest(const unsigned char *buff, int len) {}  virtual bool CanHandleEMM(int SysId) { return false; }public:  cCardClientCommon(const char *Name, bool ConReply, bool LogReply, bool DoAES, int MinMsgLen);  virtual bool Init(const char *config);  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw);  virtual bool ProcessEMM(int caSys, const unsigned char *source);  };cCardClientCommon::cCardClientCommon(const char *Name, bool ConReply, bool LogReply, bool DoAES, int MinMsgLen):cCardClient(Name),so(DEFAULT_CONNECT_TIMEOUT,CCTIMEOUT/1000,DEFAULT_IDLE_TIMEOUT){  conReply=ConReply; logReply=LogReply; doAES=DoAES; minMsgLen=MinMsgLen;  emmProcessing=exclusive=false;}bool cCardClientCommon::ParseUserConfig(const char *config, int *num){  int startNum=*num;  if(sscanf(&config[*num],":%10[^:]:%10[^:]%n",username,password,num)==2) {    *num+=startNum;    PRINTF(L_CC_CORE,"%s: username=%s password=%s",name,username,password);;    return true;    }  return false;}bool cCardClientCommon::ParseKeyConfig(const char *config, int *num){  char hexkey[33];  int startNum=*num;  if(sscanf(&config[*num],":%32[^:]%n",hexkey,num)==1) {    *num+=startNum;    PRINTF(L_CC_CORE,"%s: key=%s",name,hexkey);    unsigned char binkey[16];    memset(binkey,0,sizeof(binkey));    const char *line=hexkey;    int n=GetHex(line,binkey,sizeof(binkey),false);    if(n!=(int)sizeof(binkey))      PRINTF(L_CC_CAMD,"warning AES key not %d bytes long",(int)sizeof(binkey));    LDUMP(L_CC_CAMD,binkey,16,"AES activated key =");    SetKey(binkey);    }  return true;}bool cCardClientCommon::SendMsg(cNetSocket *so, const unsigned char *data, int len){  unsigned char buff2[minMsgLen];  if(len<minMsgLen) {    memcpy(buff2,data,len);    memset(buff2+len,0,minMsgLen-len);    data=buff2; len=minMsgLen;    }  unsigned char buff[len+16];  const int l=Encrypt(data,len,buff);  if(l>0) { data=buff; len=l; }  return cCardClient::SendMsg(so,data,len);}int cCardClientCommon::RecvMsg(cNetSocket *so, unsigned char *data, int len, int to){  int n=cCardClient::RecvMsg(so,data,len,to);  if(n>0) {    if(n&15) PRINTF(L_CC_CAMD,"AES crypted message length not a multiple of 16");    Decrypt(data,n);    }  return n;}bool cCardClientCommon::Init(const char *config){  cMutexLock lock(this);  so.Disconnect();  int num=0;  if(ParseStdConfig(config,&num) &&     ParseUserConfig(config,&num) &&     (!doAES || ParseKeyConfig(config,&num))) {    return (emmAllowed && logReply && Immediate()) ? Login() : true;    }  return false;}bool cCardClientCommon::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;  unsigned char buff[128];  if(conReply) {    if(RecvMsg(&so,buff,sizeof(buff))!=16) {      PRINTF(L_CC_CAMD,"bad connect reply");      return false;      }    }  memset(buff,0,32);  int user_len=strlen(username)+1;  memcpy(buff+1,username,user_len);  int pass_len=strlen(password)+1;  memcpy(buff+1+user_len+1,password,pass_len);  int vers_len=strlen(CCVERSION)+1;  memcpy(buff+1+user_len+pass_len+1,CCVERSION,vers_len);  PRINTF(L_CC_CAMD,"login user='%s' password=hidden version=%s",username,CCVERSION);  if(!SendMsg(&so,buff,32)) return false;  if(emmAllowed && logReply) {    PRINTF(L_CC_CAMD,"waiting for login reply ...");    int r=RecvMsg(&so,buff,sizeof(buff));    if(r>0) HandleEMMRequest(buff,r);    }  PRINTF(L_CC_LOGIN,"%s: login done",name);  return true;}bool cCardClientCommon::ProcessEMM(int caSys, const unsigned char *source){  if(emmAllowed && CanHandleEMM(caSys)) {    cMutexLock lock(this);    if(MatchEMM(source)) {      const int length=SCT_LEN(source);      int id=msEMM.Get(source,length,0);      if(id>0) {        unsigned char buff[length+32];        buff[0]=0x03;        buff[1]=(caSys>>8);        buff[2]=(caSys&0xFF);        memcpy(buff+3,((cCardIrdeto *)card)->hexSer,3);        buff[6]=((cCardIrdeto *)card)->hexBase;        memcpy(&buff[7],source,length);        //PRINTF(L_CC_CAMD,"%s: sending EMM for caid 0x%04X",name,caSys);        SendMsg(&so,buff,length+7);        msEMM.Cache(id,true,0);        }      return true;      }    }  return false;}bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw){  Lock();  bool res=false;  while(exclusive) sleepCond.Wait(*this);  if((so.Connected() || Login()) && (!emmProcessing || CanHandle(ecm->caId))) {    const int length=SCT_LEN(source);    unsigned char buff[length+32];    int n;    while((n=RecvMsg(&so,buff,16,0))>0) HandleEMMRequest(buff,n);    buff[0]=0x02;    buff[1]=(ecm->caId>>8);    buff[2]=(ecm->caId&0xFF);    memset(&buff[3],0,4);    memcpy(&buff[7],source,length);    if(SendMsg(&so,buff,length+7)) {      exclusive=true;      time.Set(CCTIMEOUT);      do {        sleepCond.TimedWait(*this,50);        while((n=RecvMsg(&so,buff,32,0))>0) {          if(n>=21 && buff[0]==2) {            if(!CheckNull(buff+5,16)) {              if(!res) {                memcpy(cw,buff+5,16);                res=true;                }              else PRINTF(L_CC_CAMD,"unexpected CW packet");              }            else {              PRINTF(L_CC_ECM,"%s: server is unable to handle ECM",name);              n=-1;              break;              }            }          else HandleEMMRequest(buff,n);          }        } 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();  return res;}// -- cCardClientCamd33 --------------------------------------------------------class cCardClientCamd33 : public cCardClientCommon {private:  int CAID;  unsigned char lastEmmReq[32];protected:  virtual void HandleEMMRequest(const unsigned char *buff, int len);  virtual bool CanHandleEMM(int SysId);public:  cCardClientCamd33(const char *Name);  virtual bool CanHandle(unsigned short SysId);  };static cCardClientLinkReg<cCardClientCamd33> __camd33("Camd33");cCardClientCamd33::cCardClientCamd33(const char *Name):cCardClientCommon(Name,true,true,true,0){  CAID=0;  memset(lastEmmReq,0,sizeof(lastEmmReq));}bool cCardClientCamd33::CanHandle(unsigned short SysId){  return CanHandleEMM(SysId) || cCardClient::CanHandle(SysId);}bool cCardClientCamd33::CanHandleEMM(int SysId){  return (emmProcessing && SysId==CAID);}void cCardClientCamd33::HandleEMMRequest(const unsigned char *buff, int len){  if(len>=13 && buff[0]==0 && !CheckNull(buff,len) && memcmp(buff,lastEmmReq,13)) {    emmProcessing=false;    CAID=buff[1]*256+buff[2];    ResetIdSet();    switch(CAID>>8) {      case 0x17:      case 0x06:        SetCard(new cCardIrdeto(buff[6],&buff[3]));        AddProv(new cProviderIrdeto(0,&buff[7]));        AddProv(new cProviderIrdeto(2,&buff[10]));        memcpy(lastEmmReq,buff,13);        PRINTF(L_CC_LOGIN,"%s: CAID: %04x HexSerial: %02X%02X%02X, HexBase: %02X",name,CAID,buff[3],buff[4],buff[5],buff[6]);        PRINTF(L_CC_LOGIN,"%s: Provider00: %02X%02X%02X, Provider10: %02X%02X%02X",name,buff[7],buff[8],buff[9],buff[10],buff[11],buff[12]);        if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);        emmProcessing=true;        break;      }    }}// -- cCardClientCardd ---------------------------------------------------------class cCardClientCardd : public cCardClientCommon {public:  cCardClientCardd(const char *Name);  };static cCardClientLinkReg<cCardClientCardd> __cardd("Cardd");cCardClientCardd::cCardClientCardd(const char *Name):cCardClientCommon(Name,false,true,false,96){}// -- cCardClientBuffy ---------------------------------------------------------#define MAX_CAIDS 16class cCardClientBuffy : public cCardClientCommon {private:  unsigned short CAIDs[MAX_CAIDS], numCAIDs;protected:  virtual bool Login(void);public:  cCardClientBuffy(const char *Name);  virtual bool Init(const char *config);  virtual bool CanHandle(unsigned short SysId);  };static cCardClientLinkReg<cCardClientBuffy> __buffy("Buffy");cCardClientBuffy::cCardClientBuffy(const char *Name):cCardClientCommon(Name,true,false,true,0){}bool cCardClientBuffy::Init(const char *config){  cMutexLock lock(this);  if(cCardClientCommon::Init(config)) {    return Immediate() ? Login() : true;    }  return false;}bool cCardClientBuffy::CanHandle(unsigned short SysId){  cMutexLock lock(this);  for(int i=0; i<numCAIDs; i++) if(CAIDs[i]==SysId) return true;  return false;}bool cCardClientBuffy::Login(void){  cMutexLock lock(this);  if(!cCardClientCommon::Login()) return false;  unsigned char buff[128];  memset(buff,0,sizeof(buff));  buff[0]=0x0A;  if(!SendMsg(&so,buff,32)) return false;  int n=RecvMsg(&so,buff,sizeof(buff));  if(n<0) return false;  for(int i=1; i<n && numCAIDs<MAX_CAIDS; i+=2) {    unsigned short caid=(buff[i+1]<<8)+buff[i];    if(caid==0xFFFF) break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -