SASC
DVBSoftCAM

cCardClientNewCamd Class Reference

Inheritance diagram for cCardClientNewCamd:

List of all members.

Public Member Functions

 cCardClientNewCamd (const char *Name)
virtual bool Init (const char *CfgDir)
virtual bool Login (void)
virtual bool CanHandle (unsigned short SysId)
virtual bool ProcessECM (const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw)
virtual bool ProcessEMM (int caSys, const unsigned char *data)
 cCardClientNewCamd (const char *Name)
virtual bool Init (const char *CfgDir)
virtual bool Login (void)
virtual bool CanHandle (unsigned short SysId)
virtual bool ProcessECM (const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw)
virtual bool ProcessEMM (int caSys, const unsigned char *data)

Detailed Description

Definition at line 168 of file newcamd.c.


Constructor & Destructor Documentation

cCardClientNewCamd::cCardClientNewCamd ( const char *  Name)

Definition at line 198 of file newcamd.c.

References cNetSocket::SetRWTimeout(), and cCardClient::so.

:cCardClient(Name)
{
  memset(username,0,sizeof(username));
  memset(password,0,sizeof(password));
  InitVars();
  InitProtoVers(525);
  so.SetRWTimeout(20*1000);
}
cCardClientNewCamd::cCardClientNewCamd ( const char *  Name)

Member Function Documentation

bool cCardClientNewCamd::CanHandle ( unsigned short  SysId) [virtual]

Reimplemented from cCardClient.

Definition at line 349 of file newcamd.c.

Referenced by ProcessECM().

{
  return (caId>=0 && (SysId==caId || (caId==0x1234 && SysId==0x1801))) || cCardClient::CanHandle(SysId);
}
virtual bool cCardClientNewCamd::CanHandle ( unsigned short  SysId) [virtual]

Reimplemented from cCardClient.

bool cCardClientNewCamd::Init ( const char *  CfgDir) [virtual]

Implements cCardClient.

Definition at line 354 of file newcamd.c.

References GetHex(), HexStr(), L_CC_CORE, cCardClient::Logout(), cCardClient::name, cCardClient::ParseStdConfig(), and PRINTF.

{
  cMutexLock lock(this);
  Logout();
  int num=0;
  char key[29];
  const char *tmp=key;
  if(!ParseStdConfig(config,&num)
     || sscanf(&config[num],":%31[^:]:%31[^:]:%28[^:]",username,password,key)!=3
     || GetHex(tmp,configKey,sizeof(configKey),false)!=14) return false;
  char str[32];
  PRINTF(L_CC_CORE,"%s: username=%s password=%s key=%s",name,username,password,HexStr(str,configKey,14));
  return true;
}
virtual bool cCardClientNewCamd::Init ( const char *  CfgDir) [virtual]

Implements cCardClient.

bool cCardClientNewCamd::Login ( void  ) [virtual]

Implements cCardClient.

Definition at line 369 of file newcamd.c.

References cProviders::AddProv(), cCardClient::CaidsChanged(), CheckNull(), cNetSocket::Connect(), CWS_NETMSGSIZE, cTripleDes::desKey, cCardClient::emmAllowed, cTripleDes::Expand(), HexStr(), cCardClient::hostname, i, L_CC_EMM, L_CC_LOGIN, L_CC_NEWCAMD, LBEND, LBPUT, LBSTARTF, cCardClient::Logout(), MSG_CARD_DATA, MSG_CARD_DATA_REQ, MSG_CLIENT_2_SERVER_LOGIN, MSG_CLIENT_2_SERVER_LOGIN_ACK, cCardClient::name, cCardClient::port, PRINTF, cNetSocket::Read(), cTripleDes::ScheduleKey(), cIdSet::SetCard(), and cCardClient::so.

Referenced by ProcessECM().

{
  Logout();
  if(!so.Connect(hostname,port)) return false;

  InitVars();
  unsigned char randData[14];
  if(so.Read(randData,sizeof(randData))<0) {
    PRINTF(L_CC_NEWCAMD,"no connect answer from %s:%d",hostname,port);
    Logout();
    return false;
    }

  char *crPasswd=crypt(password,"$1$abcdefgh$");
  unsigned char buffer[CWS_NETMSGSIZE];
  const int userLen=strlen(username)+1;
  const int passLen=strlen(crPasswd)+1;
  
  // prepare the initial login message
  buffer[0] = MSG_CLIENT_2_SERVER_LOGIN;
  buffer[1] = 0;
  buffer[2] = userLen+passLen;
  memcpy(&buffer[3],username,userLen);
  memcpy(&buffer[3]+userLen,crPasswd,passLen);

  // XOR configKey with randData and expand the 14 byte result -> 16 byte
  PrepareLoginKey(desKey,randData,configKey);
  cTripleDes::ScheduleKey();

  // set NewCS client identification
  // this seems to conflict with other cardservers e.g. rqcs !!
  //struct CustomData cd;
  //InitCustomData(&cd,0x5644,0);

  if(!SendMessage(buffer,buffer[2]+3,true) || CmdReceive()!=MSG_CLIENT_2_SERVER_LOGIN_ACK) {
    PRINTF(L_CC_NEWCAMD,"failed to login to cardserver for username %s (proto %d)",username,protoVers);
    if(NextProto()) return Login();
    return false;
    }

  // create the session key (for usage later)
  unsigned char tmpkey[14];
  memcpy(tmpkey, configKey, sizeof(tmpkey));
  const int passStrLen=strlen(crPasswd);
  for(int i=0; i<passStrLen; ++i) tmpkey[i%14]^=crPasswd[i];

  cTripleDes::Expand(desKey,tmpkey); // expand 14 byte key -> 16 byte
  cTripleDes::ScheduleKey();

  if(!CmdSend(MSG_CARD_DATA_REQ) || ReceiveMessage(buffer,false)<=0) return false;
  if(buffer[0] == MSG_CARD_DATA) {
    int c=(buffer[4]<<8)+buffer[5];
    if(c!=caId) CaidsChanged();
    caId=c;
    LBSTARTF(L_CC_LOGIN);
    char str[32], str2[32];
    LBPUT("%s: CaID=%04x admin=%d srvUA=%s",name,caId,buffer[3]==1,HexStr(str,&buffer[6],8));
    if(!CheckNull(&buffer[6],8)) {
      emmProcessing=true;
      switch(caId>>8) {
        case 0x17:
        case 0x06: SetCard(new cCardIrdeto(buffer[6+4],&buffer[6+5])); break;
        case 0x01: SetCard(new cCardSeca(&buffer[6+2])); break;
        case 0x0b: SetCard(new cCardConax(&buffer[6+1])); break;
        case 0x09: SetCard(new cCardNDS(&buffer[6+4])); break;
        case 0x05: SetCard(new cCardViaccess(&buffer[6+3])); break;
        case 0x0d: SetCard(new cCardCryptoworks(&buffer[6+3])); break;
        case 0x12:
        case 0x18: if(caId>=0x1801 || caId==0x1234) {
                     SetCard(new cCardNagra2(&buffer[6+4]));
                     break;
                     }
                   // fall through to default
        default:
          LBPUT(" (unhandled)");
          break;
        }
      }
    LBPUT(" provider");
    for(int i=(buffer[14]-1)*11; i>=0; i-=11) {
      LBPUT(" %s/%s",HexStr(str2,&buffer[15+i],3),HexStr(str,&buffer[18+i],8));
      if(!CheckNull(&buffer[18+i],8)) {
        switch(caId>>8) {
          case 0x17:
          case 0x06: AddProv(new cProviderIrdeto(buffer[18+i+4],&buffer[18+i+5])); break;
          case 0x01: AddProv(new cProviderSeca(&buffer[15+i+1],&buffer[18+i+4])); break;
          case 0x0b: AddProv(new cProviderConax(&buffer[18+i+1])); break;
          case 0x09: AddProv(new cProviderNDS(&buffer[18+i+4])); break;
          case 0x05: AddProv(new cProviderViaccess(&buffer[15+i],&buffer[18+i+4])); break;
          case 0x0d: AddProv(new cProviderCryptoworks(&buffer[18+i+3])); break;
          default:
            LBPUT(" <unhandled>");
            break;
          }
        }
      }
    LBEND();
    if(emmProcessing && !emmAllowed)
      PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
    }
  loginOK=true;
  return true;
}
virtual bool cCardClientNewCamd::Login ( void  ) [virtual]

Implements cCardClient.

bool cCardClientNewCamd::ProcessECM ( const cEcmInfo *  ecm,
const unsigned char *  data,
unsigned char *  Cw 
) [virtual]

Implements cCardClient.

Definition at line 473 of file newcamd.c.

References cEcmInfo::caId, CanHandle(), CheckNull(), cNetSocket::Connected(), CWS_NETMSGSIZE, cNetSocket::Flush(), L_CC_ECM, L_CC_NEWCAMD, Login(), cCardClient::name, cEcmInfo::prgId, PRINTF, SCT_LEN, and cCardClient::so.

{
  cMutexLock lock(this);
  if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false;
  so.Flush();

  struct CustomData cd;
  InitCustomData(&cd,(unsigned short)ecm->prgId,0);
  if(!SendMessage(data,SCT_LEN(data),true,&cd)) return false;
  unsigned char buffer[CWS_NETMSGSIZE];
  int n;
  while((n=ReceiveMessage(buffer,true))==-2)
    PRINTF(L_CC_NEWCAMD,"msg ID sync error. Retrying...");
  switch(n) {
    case 19: // ecm was decoded
      // check for zero cw, as newcs doesn't send both cw's every time
      if(!CheckNull(buffer+3+0,8)) memcpy(cw+0,buffer+3+0,8);
      if(!CheckNull(buffer+3+8,8)) memcpy(cw+8,buffer+3+8,8);
      return true;
    case 3:
      PRINTF(L_CC_ECM,"%s: card was not able to decode the channel",name);
      break;
    default:
      PRINTF(L_CC_NEWCAMD,"unexpected server response (code %d)",n);
      break;
    }
  return false;
}
virtual bool cCardClientNewCamd::ProcessECM ( const cEcmInfo *  ecm,
const unsigned char *  data,
unsigned char *  Cw 
) [virtual]

Implements cCardClient.

virtual bool cCardClientNewCamd::ProcessEMM ( int  caSys,
const unsigned char *  data 
) [virtual]

Reimplemented from cCardClient.

bool cCardClientNewCamd::ProcessEMM ( int  caSys,
const unsigned char *  data 
) [virtual]

Reimplemented from cCardClient.

Definition at line 502 of file newcamd.c.

References cAssembleData::Assembled(), cMsgCache::Cache(), CWS_NETMSGSIZE, cCardClient::emmAllowed, cMsgCache::Get(), L_CC_EMM, L_CC_NEWCAMD, cIdSet::MatchAndAssemble(), cCardClient::msEMM, PRINTF, and SCT_LEN.

{
  if(emmProcessing && emmAllowed) {
    cMutexLock lock(this);
    cAssembleData ad(data);
    if(MatchAndAssemble(&ad,0,0)) {
      while((data=ad.Assembled())) {
        int len=SCT_LEN(data);
        int id=msEMM.Get(data,len,0);
        if(id>0 || emmAllowed>1) {
          if(SendMessage(data,len,true,0)) {
            unsigned char buffer[CWS_NETMSGSIZE];
            len=ReceiveMessage(buffer,true);
            if(len>=3) {
              if(!(buffer[1]&0x10))
                PRINTF(L_CC_EMM,"EMM rejected by card");
              }
            else
              PRINTF(L_CC_NEWCAMD,"unexpected server response (code %d)",len);
            }
          msEMM.Cache(id,true,0);
          }
        }
      return true;
      }
    }
  return false;
}

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines