|
SASC-NG
DVBSoftCAM
|
00001 /* 00002 * Softcam plugin to VDR (C++) 00003 * 00004 * This code is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This code is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00018 */ 00019 00020 #include <stdio.h> 00021 #include <string.h> 00022 #include <byteswap.h> 00023 00024 #include "cc.h" 00025 #include "crypto.h" 00026 #include "misc.h" 00027 #include "parse.h" 00028 00029 #include <openssl/md5.h> 00030 00031 #define CCVERSION "3.37" 00032 #define CCTIMEOUT 5000 // ms 00033 00034 // -- cCardClientCommon -------------------------------------------------------- 00035 00036 class cCardClientCommon : public cCardClient, public cAES, protected cIdSet { 00037 private: 00038 bool conReply, logReply, doAES; 00039 bool exclusive; 00040 int minMsgLen; 00041 cCondVar sleepCond; 00042 cTimeMs time; 00043 protected: 00044 bool emmProcessing; 00045 char username[11], password[11]; 00046 int emmReqLen; 00047 // 00048 bool ParseKeyConfig(const char *config, int *num); 00049 bool ParseUserConfig(const char *config, int *num); 00050 virtual bool SendMsg(const unsigned char *data, int len); 00051 virtual int RecvMsg(unsigned char *data, int len, int to=-1); 00052 virtual void HandleEMMRequest(const unsigned char *buff, int len) {} 00053 virtual bool CanHandleEMM(int SysId) { return false; } 00054 public: 00055 cCardClientCommon(const char *Name, bool ConReply, bool LogReply, bool DoAES, int MinMsgLen); 00056 virtual bool Init(const char *config); 00057 virtual bool Login(void); 00058 virtual bool Immediate(void); 00059 virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw); 00060 virtual bool ProcessEMM(int caSys, const unsigned char *source); 00061 }; 00062 00063 cCardClientCommon::cCardClientCommon(const char *Name, bool ConReply, bool LogReply, bool DoAES, int MinMsgLen) 00064 :cCardClient(Name) 00065 { 00066 conReply=ConReply; logReply=LogReply; doAES=DoAES; minMsgLen=MinMsgLen; 00067 emmProcessing=exclusive=false; 00068 so.SetRWTimeout(CCTIMEOUT); 00069 emmReqLen=-64; 00070 } 00071 00072 bool cCardClientCommon::ParseUserConfig(const char *config, int *num) 00073 { 00074 int startNum=*num; 00075 if(sscanf(&config[*num],":%10[^:]:%10[^:]%n",username,password,num)==2) { 00076 *num+=startNum; 00077 PRINTF(L_CC_CORE,"%s: username=%s password=%s",name,username,password);; 00078 return true; 00079 } 00080 return false; 00081 } 00082 00083 bool cCardClientCommon::ParseKeyConfig(const char *config, int *num) 00084 { 00085 char hexkey[33]; 00086 int startNum=*num; 00087 if(sscanf(&config[*num],":%32[^:]%n",hexkey,num)==1) { 00088 *num+=startNum; 00089 PRINTF(L_CC_CORE,"%s: key=%s",name,hexkey); 00090 unsigned char binkey[16]; 00091 memset(binkey,0,sizeof(binkey)); 00092 const char *line=hexkey; 00093 int n=GetHex(line,binkey,sizeof(binkey),false); 00094 if(n!=(int)sizeof(binkey)) 00095 PRINTF(L_CC_CAMD,"warning AES key not %d bytes long",(int)sizeof(binkey)); 00096 LDUMP(L_CC_CAMD,binkey,16,"AES activated key ="); 00097 SetKey(binkey); 00098 } 00099 return true; 00100 } 00101 00102 bool cCardClientCommon::SendMsg(const unsigned char *data, int len) 00103 { 00104 unsigned char *buff2=AUTOMEM(minMsgLen); 00105 if(len<minMsgLen) { 00106 memcpy(buff2,data,len); 00107 memset(buff2+len,0,minMsgLen-len); 00108 data=buff2; len=minMsgLen; 00109 } 00110 unsigned char *buff=AUTOMEM(len+16); 00111 const int l=Encrypt(data,len,buff); 00112 if(l>0) { data=buff; len=l; } 00113 return cCardClient::SendMsg(data,len); 00114 } 00115 00116 int cCardClientCommon::RecvMsg(unsigned char *data, int len, int to) 00117 { 00118 int n=cCardClient::RecvMsg(data,len,to); 00119 if(n>0) { 00120 if(n&15) PRINTF(L_CC_CAMD,"AES crypted message length not a multiple of 16"); 00121 Decrypt(data,n); 00122 } 00123 return n; 00124 } 00125 00126 bool cCardClientCommon::Immediate(void) 00127 { 00128 return emmAllowed && logReply && cCardClient::Immediate(); 00129 } 00130 00131 bool cCardClientCommon::Init(const char *config) 00132 { 00133 cMutexLock lock(this); 00134 Logout(); 00135 int num=0; 00136 if(ParseStdConfig(config,&num) && 00137 ParseUserConfig(config,&num) && 00138 (!doAES || ParseKeyConfig(config,&num))) { 00139 return true; 00140 } 00141 return false; 00142 } 00143 00144 bool cCardClientCommon::Login(void) 00145 { 00146 Logout(); 00147 if(!so.Connect(hostname,port)) return false; 00148 PRINTF(L_CC_LOGIN,"%s: connected to %s:%d (%s)",name,hostname,port,name); 00149 emmProcessing=false; 00150 00151 unsigned char buff[128]; 00152 if(conReply) { 00153 if(RecvMsg(buff,16)<0) { 00154 PRINTF(L_CC_CAMD,"bad connect reply"); 00155 return false; 00156 } 00157 } 00158 00159 memset(buff,0,32); 00160 int user_len=strlen(username)+1; 00161 memcpy(buff+1,username,user_len); 00162 int pass_len=strlen(password)+1; 00163 memcpy(buff+1+user_len+1,password,pass_len); 00164 int vers_len=strlen(CCVERSION)+1; 00165 memcpy(buff+1+user_len+pass_len+1,CCVERSION,vers_len); 00166 PRINTF(L_CC_CAMD,"login user='%s' password=hidden version=%s",username,CCVERSION); 00167 if(!SendMsg(buff,32)) return false; 00168 00169 if(emmAllowed && logReply) { 00170 PRINTF(L_CC_CAMD,"waiting for login reply ..."); 00171 int r=RecvMsg(buff,emmReqLen); 00172 if(r>0) HandleEMMRequest(buff,r); 00173 } 00174 PRINTF(L_CC_LOGIN,"%s: login done",name); 00175 return true; 00176 } 00177 00178 bool cCardClientCommon::ProcessEMM(int caSys, const unsigned char *source) 00179 { 00180 if(emmAllowed && CanHandleEMM(caSys)) { 00181 cMutexLock lock(this); 00182 if(MatchEMM(source)) { 00183 const int length=SCT_LEN(source); 00184 int id=msEMM.Get(source,length,0); 00185 if(id>0 || emmAllowed>1) { 00186 unsigned char *buff=AUTOMEM(length+32); 00187 buff[0]=0x03; 00188 buff[1]=(caSys>>8); 00189 buff[2]=(caSys&0xFF); 00190 memcpy(buff+3,((cCardIrdeto *)card)->hexSer,3); 00191 buff[6]=((cCardIrdeto *)card)->hexBase; 00192 memcpy(&buff[7],source,length); 00193 //PRINTF(L_CC_CAMD,"%s: sending EMM for caid 0x%04X",name,caSys); 00194 SendMsg(buff,length+7); 00195 msEMM.Cache(id,true,0); 00196 } 00197 return true; 00198 } 00199 } 00200 return false; 00201 } 00202 00203 bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw) 00204 { 00205 Lock(); 00206 bool res=false; 00207 while(exclusive) sleepCond.Wait(*this); 00208 if((so.Connected() || Login()) && (!emmProcessing || CanHandle(ecm->caId))) { 00209 const int length=SCT_LEN(source); 00210 unsigned char *buff=AUTOMEM(length+32); 00211 int n; 00212 while((n=RecvMsg(buff,-16,0))>0) HandleEMMRequest(buff,n); 00213 buff[0]=0x02; 00214 buff[1]=(ecm->caId>>8); 00215 buff[2]=(ecm->caId&0xFF); 00216 memset(&buff[3],0,4); 00217 memcpy(&buff[7],source,length); 00218 if(SendMsg(buff,length+7)) { 00219 exclusive=true; 00220 time.Set(CCTIMEOUT); 00221 do { 00222 sleepCond.TimedWait(*this,50); 00223 while((n=RecvMsg(buff,-32,0))>0) { 00224 if(n>=21 && buff[0]==2) { 00225 if(!CheckNull(buff+5,16)) { 00226 if(!res) { 00227 memcpy(cw,buff+5,16); 00228 res=true; 00229 } 00230 else PRINTF(L_CC_CAMD,"unexpected CW packet"); 00231 } 00232 else { 00233 PRINTF(L_CC_ECM,"%s: server is unable to handle ECM",name); 00234 n=-1; 00235 break; 00236 } 00237 } 00238 else HandleEMMRequest(buff,n); 00239 } 00240 } while(!res && n>=0 && !time.TimedOut()); 00241 if(!res && time.TimedOut()) PRINTF(L_CC_ECM,"%s: CW request timed out",name); 00242 exclusive=false; 00243 sleepCond.Broadcast(); 00244 } 00245 } 00246 Unlock(); 00247 return res; 00248 } 00249 00250 // -- cCardClientCamd33 -------------------------------------------------------- 00251 00252 #define EMMREQLEN33 13 00253 00254 class cCardClientCamd33 : public cCardClientCommon { 00255 private: 00256 int CAID; 00257 unsigned char lastEmmReq[32]; 00258 protected: 00259 virtual void HandleEMMRequest(const unsigned char *buff, int len); 00260 virtual bool CanHandleEMM(int SysId); 00261 public: 00262 cCardClientCamd33(const char *Name); 00263 virtual bool CanHandle(unsigned short SysId); 00264 }; 00265 00266 static cCardClientLinkReg<cCardClientCamd33> __camd33("Camd33"); 00267 00268 cCardClientCamd33::cCardClientCamd33(const char *Name) 00269 :cCardClientCommon(Name,true,true,true,0) 00270 { 00271 CAID=0; 00272 memset(lastEmmReq,0,sizeof(lastEmmReq)); 00273 emmReqLen=EMMREQLEN33; 00274 } 00275 00276 bool cCardClientCamd33::CanHandle(unsigned short SysId) 00277 { 00278 return CanHandleEMM(SysId) || cCardClient::CanHandle(SysId); 00279 } 00280 00281 bool cCardClientCamd33::CanHandleEMM(int SysId) 00282 { 00283 return (emmProcessing && SysId==CAID); 00284 } 00285 00286 void cCardClientCamd33::HandleEMMRequest(const unsigned char *buff, int len) 00287 { 00288 if(len>=emmReqLen && buff[0]==0 && !CheckNull(buff,len) && memcmp(buff,lastEmmReq,emmReqLen)) { 00289 emmProcessing=false; 00290 int c=buff[1]*256+buff[2]; 00291 if(c!=CAID) CaidsChanged(); 00292 CAID=c; 00293 ResetIdSet(); 00294 switch(CAID>>8) { 00295 case 0x17: 00296 case 0x06: 00297 SetCard(new cCardIrdeto(buff[6],&buff[3])); 00298 AddProv(new cProviderIrdeto(0,&buff[7])); 00299 AddProv(new cProviderIrdeto(2,&buff[10])); 00300 memcpy(lastEmmReq,buff,13); 00301 PRINTF(L_CC_LOGIN,"%s: CAID: %04x HexSerial: %02X%02X%02X, HexBase: %02X",name,CAID,buff[3],buff[4],buff[5],buff[6]); 00302 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]); 00303 if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name); 00304 emmProcessing=true; 00305 break; 00306 } 00307 } 00308 } 00309 00310 // -- cCardClientCardd --------------------------------------------------------- 00311 00312 class cCardClientCardd : public cCardClientCommon { 00313 public: 00314 cCardClientCardd(const char *Name); 00315 }; 00316 00317 static cCardClientLinkReg<cCardClientCardd> __cardd("Cardd"); 00318 00319 cCardClientCardd::cCardClientCardd(const char *Name) 00320 :cCardClientCommon(Name,false,true,false,96) 00321 {} 00322 00323 // -- cCardClientBuffy --------------------------------------------------------- 00324 00325 #define MAX_CAIDS 16 00326 00327 class cCardClientBuffy : public cCardClientCommon { 00328 private: 00329 unsigned short CAIDs[MAX_CAIDS], numCAIDs; 00330 public: 00331 cCardClientBuffy(const char *Name); 00332 virtual bool Init(const char *config); 00333 virtual bool Login(void); 00334 virtual bool CanHandle(unsigned short SysId); 00335 }; 00336 00337 static cCardClientLinkReg<cCardClientBuffy> __buffy("Buffy"); 00338 00339 cCardClientBuffy::cCardClientBuffy(const char *Name) 00340 :cCardClientCommon(Name,true,false,true,0) 00341 {} 00342 00343 bool cCardClientBuffy::Init(const char *config) 00344 { 00345 cMutexLock lock(this); 00346 return cCardClientCommon::Init(config); 00347 } 00348 00349 bool cCardClientBuffy::CanHandle(unsigned short SysId) 00350 { 00351 cMutexLock lock(this); 00352 for(int i=0; i<numCAIDs; i++) if(CAIDs[i]==SysId) return true; 00353 return false; 00354 } 00355 00356 bool cCardClientBuffy::Login(void) 00357 { 00358 cMutexLock lock(this); 00359 if(!cCardClientCommon::Login()) return false; 00360 00361 unsigned char buff[128]; 00362 memset(buff,0,sizeof(buff)); 00363 buff[0]=0x0A; 00364 if(!SendMsg(buff,32)) return false; 00365 int n=RecvMsg(buff,-sizeof(buff)); 00366 if(n<0) return false; 00367 for(int i=1; i<n && numCAIDs<MAX_CAIDS; i+=2) { 00368 unsigned short caid=(buff[i+1]<<8)+buff[i]; 00369 if(caid==0xFFFF) break; 00370 if(caid) CAIDs[numCAIDs++]=caid; 00371 } 00372 CaidsChanged(); 00373 LBSTART(L_CC_LOGIN); 00374 LBPUT("%s: CAIDs ",name); 00375 for(int i=0; i<numCAIDs && CAIDs[i]; i++) LBPUT("%04X ",CAIDs[i]); 00376 LBEND(); 00377 return true; 00378 } 00379 00380 // -- cCardClientCamd35 -------------------------------------------------------- 00381 00382 struct CmdBlock { 00383 unsigned int ucrc; 00384 struct { 00385 unsigned char cmd; // 0 00386 unsigned char len; // 1 00387 unsigned char pad[2]; // 2 XXXX 00388 unsigned int crc; // 4 00389 } udp_header; 00390 struct { 00391 unsigned short srvID; // 8 00392 unsigned short casID; // 10 00393 unsigned int prvID; // 12 00394 unsigned short pinID; // 16 00395 unsigned char pad2[2];// 18 XXXX 00396 } service; 00397 unsigned char data[2]; // 20 00398 }; 00399 00400 #define CBSIZE(cb) (sizeof((cb)->udp_header)+sizeof((cb)->service)) 00401 #define UCSIZE(cb) (sizeof((cb)->ucrc)) 00402 #define HDSIZE(cb) (CBSIZE(cb)+UCSIZE(cb)) 00403 00404 struct EmmReq02 { 00405 unsigned short caid; 00406 unsigned char hex[4]; 00407 unsigned char D0, D2, D3; 00408 }; 00409 00410 struct EmmReq05 { 00411 unsigned short caids[8]; // 0 00412 int caidCount; // 16 00413 unsigned char ua[6]; // 20 00414 unsigned short provMap; // 26 00415 struct { // 28 00416 unsigned char prov[2]; 00417 unsigned char sa[3]; 00418 } provInfo[16]; 00419 unsigned char D0, D2, D3; // 108 00420 }; 00421 00422 class cCardClientCamd35 : public cCardClient, public cAES, private cIdSet { 00423 private: 00424 unsigned int ucrc; 00425 unsigned short pinid; 00426 bool exclusive, emmCmd06; 00427 cCondVar sleepCond; 00428 cTimeMs time; 00429 protected: 00430 bool emmProcessing; 00431 char username[33], password[33]; 00432 int numCaids, Caids[8]; 00433 unsigned char Dx[8]; 00434 int lastEmmReq; 00435 // 00436 bool ParseUserConfig(const char *config, int *num); 00437 bool SendBlock(struct CmdBlock *cb, int datalen); 00438 int RecvBlock(struct CmdBlock *cb, int maxlen, int to); 00439 void HandleEMMRequest(const struct CmdBlock *cb); 00440 bool CanHandleEMM(unsigned short SysId); 00441 public: 00442 cCardClientCamd35(const char *Name); 00443 virtual bool Init(const char *config); 00444 virtual bool Login(void); 00445 virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw); 00446 virtual bool ProcessEMM(int caSys, const unsigned char *data); 00447 }; 00448 00449 static cCardClientLinkReg<cCardClientCamd35> __camd35("Camd35"); 00450 00451 cCardClientCamd35::cCardClientCamd35(const char *Name) 00452 :cCardClient(Name) 00453 { 00454 emmProcessing=exclusive=emmCmd06=false; pinid=0; numCaids=0; lastEmmReq=0; 00455 memset(Dx,0,sizeof(Dx)); 00456 so.SetRWTimeout(CCTIMEOUT); 00457 so.SetUDP(true); 00458 } 00459 00460 bool cCardClientCamd35::ParseUserConfig(const char *config, int *num) 00461 { 00462 int startNum=*num; 00463 if(sscanf(&config[*num],":%32[^:]:%32[^:]%n",username,password,num)==2) { 00464 *num+=startNum; 00465 unsigned char md[16]; 00466 ucrc=bswap_32(crc32_le(0,MD5((unsigned char *)username,strlen(username),md),16)); 00467 PRINTF(L_CC_CORE,"%s: username=%s password=%s ucrc=%08x",name,username,password,ucrc);; 00468 SetKey(MD5((unsigned char *)password,strlen(password),md)); 00469 return true; 00470 } 00471 return false; 00472 } 00473 00474 bool cCardClientCamd35::SendBlock(struct CmdBlock *cb, int datalen) 00475 { 00476 cb->udp_header.len=datalen; 00477 cb->udp_header.crc=bswap_32(crc32_le(0,&cb->data[0],datalen)); 00478 datalen+=CBSIZE(cb); 00479 unsigned char *buff=AUTOMEM(datalen+UCSIZE(cb)+16); 00480 *((unsigned int *)buff)=ucrc; 00481 HEXDUMP(L_CC_CAMDEXTR,cb,datalen+UCSIZE(cb),"send:"); 00482 const int l=Encrypt((unsigned char *)cb+UCSIZE(cb),datalen,buff+UCSIZE(cb)); 00483 if(l<=0) return false; 00484 return cCardClient::SendMsg(buff,l+UCSIZE(cb)); 00485 } 00486 00487 int cCardClientCamd35::RecvBlock(struct CmdBlock *cb, int maxlen, int to) 00488 { 00489 unsigned char *m=(unsigned char *)cb; 00490 int n=cCardClient::RecvMsg(m,-maxlen,to); 00491 if(n<=0) return n; 00492 if((unsigned int)n>=HDSIZE(cb)) { 00493 if(cb->ucrc==ucrc) { 00494 Decrypt(m+UCSIZE(cb),n-UCSIZE(cb)); 00495 if((unsigned int)n<cb->udp_header.len+HDSIZE(cb)) 00496 PRINTF(L_CC_CAMD35,"packet length doesn't match data length"); 00497 else if(cb->udp_header.crc!=bswap_32(crc32_le(0,&cb->data[0],cb->udp_header.len))) 00498 PRINTF(L_CC_CAMD35,"data crc failed"); 00499 else { 00500 HEXDUMP(L_CC_CAMDEXTR,cb,n,"recv:"); 00501 return n; 00502 } 00503 } 00504 else PRINTF(L_CC_CAMD35,"wrong ucrc: got %08x, want %08x",cb->ucrc,ucrc); 00505 } 00506 else PRINTF(L_CC_CAMD35,"short packet received"); 00507 return -1; 00508 } 00509 00510 bool cCardClientCamd35::Init(const char *config) 00511 { 00512 cMutexLock lock(this); 00513 Logout(); 00514 int num=0; 00515 return (ParseStdConfig(config,&num) && ParseUserConfig(config,&num)); 00516 } 00517 00518 bool cCardClientCamd35::Login(void) 00519 { 00520 Logout(); 00521 if(!so.Connect(hostname,port)) return false; 00522 PRINTF(L_CC_LOGIN,"%s: connected to %s:%d (%s)",name,hostname,port,name); 00523 emmProcessing=false; lastEmmReq=0; 00524 PRINTF(L_CC_LOGIN,"%s: login done",name); 00525 return true; 00526 } 00527 00528 void cCardClientCamd35::HandleEMMRequest(const struct CmdBlock *cb) 00529 { 00530 int c=crc32_le(0,cb->data,cb->udp_header.len); 00531 if(c!=lastEmmReq) { 00532 lastEmmReq=c; 00533 ResetIdSet(); 00534 if(cb->udp_header.cmd==0x02 && cb->udp_header.len>=9) { 00535 struct EmmReq02 *req=(struct EmmReq02 *)cb->data; 00536 numCaids=1; 00537 Caids[0]=bswap_16(req->caid); 00538 SetCard(new cCardIrdeto(req->hex[3],&req->hex[0])); 00539 Dx[0]=req->D0; 00540 Dx[2]=req->D2; 00541 Dx[3]=req->D3; 00542 char str[20]; 00543 PRINTF(L_CC_LOGIN,"%s: CAID: %04x HexSerial: %s, HexBase: %02X (D0-%d D2-%d D3-%d)\n", 00544 name,Caids[0],HexStr(str,((cCardIrdeto *)card)->hexSer,3),((cCardIrdeto *)card)->hexBase, 00545 Dx[0],Dx[2],Dx[3]); 00546 if(!emmProcessing || emmCmd06) PRINTF(L_CC_CAMD35,"got cmd 02, doing cmd02 EMM"); 00547 emmCmd06=false; 00548 } 00549 else if(cb->udp_header.cmd==0x05 && cb->udp_header.len>=111) { 00550 struct EmmReq05 *req=(struct EmmReq05 *)cb->data; 00551 numCaids=bswap_32(req->caidCount); 00552 for(int i=numCaids-1; i>=0; i--) Caids[i]=bswap_16(req->caids[i]); 00553 LBSTARTF(L_CC_LOGIN); 00554 LBPUT("%s: CAIDS:",name); 00555 for(int i=numCaids-1; i>=0; i--) LBPUT(" %04x",Caids[i]); 00556 char str[20], str2[20]; 00557 LBPUT(" ua=%s",HexStr(str,req->ua,6)); 00558 switch(Caids[0]>>8) { 00559 case 0x17: 00560 case 0x06: SetCard(new cCardIrdeto(req->ua[3],&req->ua[0])); break; 00561 case 0x01: SetCard(new cCardSeca(&req->ua[0])); break; 00562 case 0x0d: SetCard(new cCardCryptoworks(&req->ua[0])); break; 00563 case 0x05: SetCard(new cCardViaccess(&req->ua[0])); break; 00564 case 0x18: SetCard(new cCardNagra2(&req->ua[2])); break; 00565 default: 00566 LBPUT(" (unhandled)"); 00567 break; 00568 } 00569 LBPUT(" providers"); 00570 int map=bswap_16(req->provMap); 00571 // for(int i=0; i<15; i++) //XXX not sure what actualy is the correct 00572 // if(map & (1<<i)) { //XXX interpretation of provMap 00573 for(int i=0; i<map && i<15; i++) { 00574 LBPUT(" %d:%s/%s",i,HexStr(str,req->provInfo[i].prov,2),HexStr(str2,req->provInfo[i].sa,3)); 00575 if(!CheckNull(req->provInfo[i].sa,3) && !CheckFF(req->provInfo[i].sa,3)) { 00576 switch(Caids[0]>>8) { 00577 case 0x17: 00578 case 0x06: AddProv(new cProviderIrdeto(req->provInfo[i].prov[0],req->provInfo[i].sa)); break; 00579 case 0x01: AddProv(new cProviderSeca(req->provInfo[i].prov,req->provInfo[i].sa)); break; 00580 default: 00581 LBPUT(" <unhandled>"); 00582 break; 00583 } 00584 } 00585 } 00586 Dx[0]=req->D0; 00587 Dx[2]=req->D2; 00588 Dx[3]=req->D3; 00589 LBPUT(" (D0-%d D2-%d D3-%d)",Dx[0],Dx[2],Dx[3]); 00590 LBEND(); 00591 00592 if(!emmProcessing || !emmCmd06) PRINTF(L_CC_CAMD35,"got cmd 05, doing cmd06 EMM"); 00593 emmCmd06=true; 00594 } 00595 else return; 00596 00597 if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name); 00598 emmProcessing=true; 00599 CaidsChanged(); 00600 } 00601 } 00602 00603 bool cCardClientCamd35::CanHandleEMM(unsigned short SysId) 00604 { 00605 for(int i=numCaids-1; i>=0; i--) if(SysId==Caids[i]) return true; 00606 return false; 00607 } 00608 00609 bool cCardClientCamd35::ProcessEMM(int caSys, const unsigned char *data) 00610 { 00611 if(emmProcessing && emmAllowed) { 00612 cMutexLock lock(this); 00613 PRINTF(L_CC_CAMDEXTR,"got EMM caSys=%.4x",caSys); 00614 if(CanHandleEMM(caSys)) { 00615 LDUMP(L_CC_CAMDEXTR,&data[0],10,"EMM starts with"); 00616 int upd; 00617 cProvider *p; 00618 cAssembleData ad(data); 00619 if(MatchAndAssemble(&ad,&upd,&p)) { 00620 PRINTF(L_CC_CAMDEXTR,"EMM matched upd=%d provId=%.4llx",upd,p ? p->ProvId() : 0); 00621 while((data=ad.Assembled())) { 00622 LDUMP(L_CC_CAMDEXTR,&data[0],10,"processing assembled EMM"); 00623 if(Dx[upd]) { 00624 unsigned char buff[300]; 00625 memset(buff,0xff,sizeof(buff)); 00626 struct CmdBlock *cb=(struct CmdBlock *)buff; 00627 cb->udp_header.cmd=emmCmd06 ? 0x06 : 0x02; 00628 cb->service.srvID=0; 00629 cb->service.casID=bswap_16(caSys); 00630 cb->service.prvID=bswap_32(p ? p->ProvId() : 0); 00631 cb->service.pinID=pinid++; 00632 int len=SCT_LEN(data), off=0; 00633 switch(caSys>>8) { 00634 case 0x0d: 00635 { 00636 static const unsigned char head[] = { 0x8F,0x70,0x00,0xA4,0x42,0x00,0x00,0x00 }; 00637 int c, n; 00638 switch(data[0]) { 00639 case 0x82: c=0x42; n=10; break; 00640 case 0x84: c=0x48; n=9; break; 00641 case 0x88: 00642 case 0x89: c=0x44; n=5; break; 00643 default: continue; 00644 } 00645 if(len<n) continue; 00646 off=sizeof(head); 00647 memcpy(&cb->data[0],head,off); 00648 cb->data[3+1]=c; 00649 cb->data[3+4]=len-n; 00650 SetSctLen(&cb->data[0],len-n+5); 00651 data+=n; len-=n; 00652 break; 00653 } 00654 } 00655 if(len+off<=255) { 00656 memcpy(&cb->data[off],data,len); 00657 int id=msEMM.Get(&cb->data[0],len+off,0); 00658 if(id>0 || emmAllowed>1) { 00659 SendBlock(cb,len+off); 00660 msEMM.Cache(id,true,0); 00661 } 00662 else PRINTF(L_CC_CAMDEXTR,"not send, already in cache"); 00663 } 00664 else PRINTF(L_CC_EMM,"%s: EMM length %d > 255, not supported by UDP protocol",name,len+off); 00665 } 00666 else PRINTF(L_CC_CAMDEXTR,"dropped, updtype %d blocked",upd); 00667 } 00668 return true; 00669 } 00670 else PRINTF(L_CC_CAMDEXTR,"dropped, doesn't match card data"); 00671 } 00672 else PRINTF(L_CC_CAMDEXTR,"dropped, doesn't want caSys %.4x",caSys); 00673 } 00674 return false; 00675 } 00676 00677 bool cCardClientCamd35::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw) 00678 { 00679 bool res=false; 00680 const int length=SCT_LEN(data); 00681 if(length<=255) { 00682 Lock(); 00683 while(exclusive) sleepCond.Wait(*this); 00684 unsigned char buff[300]; 00685 memset(buff,0xff,sizeof(buff)); 00686 struct CmdBlock *cb=(struct CmdBlock *)buff; 00687 const unsigned short pid=pinid++; 00688 int n; 00689 while((n=RecvBlock(cb,sizeof(buff),0))>0) { 00690 if(cb->udp_header.cmd==0x01 || cb->udp_header.cmd==0x44) 00691 PRINTF(L_CC_CAMD35,"unexpected CW answer on flush"); 00692 else 00693 HandleEMMRequest(cb); 00694 } 00695 cb->udp_header.cmd=0x00; 00696 cb->service.srvID=bswap_16(ecm->prgId); 00697 cb->service.casID=bswap_16(ecm->caId); 00698 cb->service.prvID=bswap_32(ecm->provId); 00699 cb->service.pinID=pid; 00700 memcpy(&cb->data[0],data,length); 00701 if(SendBlock(cb,length)) { 00702 exclusive=true; 00703 time.Set(CCTIMEOUT); 00704 do { 00705 sleepCond.TimedWait(*this,50); 00706 while((n=RecvBlock(cb,sizeof(buff),0))>0) { 00707 if(cb->udp_header.cmd==0x01) { 00708 if(cb->udp_header.len>=16 && cb->service.pinID==pid && !res) { 00709 if(!CheckNull(&cb->data[0],8)) memcpy(&cw[0],&cb->data[0],8); 00710 if(!CheckNull(&cb->data[8],8)) memcpy(&cw[8],&cb->data[8],8); 00711 res=true; 00712 } 00713 else PRINTF(L_CC_CAMD35,"unexpected/bad CW packet"); 00714 } 00715 else if(cb->udp_header.cmd==0x44) { 00716 if(cb->service.pinID==pid) { 00717 PRINTF(L_CC_ECM,"%s: server is unable to handle ECM",name); 00718 n=-1; 00719 break; 00720 } 00721 } 00722 else HandleEMMRequest(cb); 00723 } 00724 } while(!res && n>=0 && !time.TimedOut()); 00725 if(!res && time.TimedOut()) PRINTF(L_CC_ECM,"%s: CW request timed out",name); 00726 exclusive=false; 00727 sleepCond.Broadcast(); 00728 } 00729 Unlock(); 00730 } 00731 else PRINTF(L_CC_ECM,"%s: ECM length %d > 255, not supported by UDP protocol",name,length); 00732 return res; 00733 }