./ MultiCS.r82 / cli-newcamd.c
static char string_newcamd[] = "Newcamd"; static char string_mgcamd[] = "Mgcamd"; static char string_newcamd_mcs[] = "Newcamd-MCS"; static char string_mgcamd_mcs[] = "Mgcamd-MCS"; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int cs_connect_srv(struct server_data *srv, int fd) { char passwdcrypt[120]; unsigned char keymod[14]; int i,index,len; unsigned char buf[CWS_NETMSGSIZE]; unsigned char sessionkey[16]; // INIT srv->progname = NULL; memset( srv->version, 0, sizeof(srv->version) ); memset( srv->build, 0, 32); // if( recv_nonb(fd, keymod, 14,5000) != 14 ) { static char msg[]= "Server does not return init sequence"; srv->statmsg = msg; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server does not return init sequence\n"); return -1; } // Check Multics int ismultics = 0; uint8_t a = (keymod[0]^'M') + keymod[1] + keymod[2]; uint8_t b = keymod[4] + (keymod[5]^'C') + keymod[6]; uint8_t c = keymod[8] + keymod[9] + (keymod[10]^'S'); if ( (a==keymod[3])&&(b==keymod[7])&&(c==keymod[11]) ) { ismultics = 1; } //debugdump(keymod,14,"Recv DES Key: "); des_login_key_get(keymod, srv->key, 14, sessionkey); //debugdump(sessionkey,16,"Login Key: "); // 3. Send login info struct cs_custom_data clicd; // Custom data memset( &clicd, 0, sizeof(clicd)); //clicd.sid = 0x4343; // CCcam clicd.sid = cfg.newcamd.clientid; // Mgcamd index = 3; buf[0] = MSG_CLIENT_2_SERVER_LOGIN; buf[1] = 0; strcpy( (char*)&buf[3], srv->user); index += strlen(srv->user)+1; __md5_crypt(srv->pass, "$1$abcdefgh$",passwdcrypt); //debugf(getdbgflag(DBG_SERVER,0,srv->id)," passwdcrypt = %s\n",passwdcrypt); strcpy((char*)buf+index, (char*)passwdcrypt); index+=strlen(passwdcrypt)+1; if (ismultics) clicd.provid=0x0057484F; if ( !cs_message_send(fd, &clicd, buf, index, sessionkey) ) return -1; srv->ping = GetTickCount(); // 3.1 Get login answer len = cs_message_receive(fd, &clicd, buf, sessionkey,15000); if (len<3) { static char msg[]= "Login error"; srv->statmsg = msg; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: login answer length error (%d) from server (%s:%d)\n",len, srv->host->name,srv->port); return INVALID_SOCKET; } if ( buf[0] == MSG_CLIENT_2_SERVER_LOGIN_NAK ) { static char msg[]= "Invalid user/pass"; srv->statmsg = msg; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: login failed to server (%s:%d)\n", srv->host->name,srv->port); return -1; } else if( buf[0] != MSG_CLIENT_2_SERVER_LOGIN_ACK ) { static char msg[]= "Login error"; srv->statmsg = msg; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: Error, expected MSG_CLIENT_2_SERVER_LOGIN_ACK\n"); return -1; } else debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: connect to server (%s:%d) user '%s'\n", srv->host->name, srv->port, srv->user); // Ping srv->ping = GetTickCount()-srv->ping; // mgcamd protocol version? if (clicd.sid==0x6E73) { //&&( (clicd.provid>>24)==0x14) ) { if (ismultics) srv->progname = string_mgcamd_mcs; else srv->progname = string_mgcamd; } else if (clicd.provid==0x004D4353) { sprintf( srv->version, "r%d", clicd.sid); srv->progname = string_newcamd_mcs; } else srv->progname = string_newcamd; // des_login_key_get( srv->key, (uint8_t*)passwdcrypt, strlen(passwdcrypt), sessionkey); //debugdump(sessionkey,16,"sessionkey: "); memcpy( srv->sessionkey, sessionkey,16); // 4. Send MSG_CARD_DATA_REQ memset( &clicd, 0, sizeof(clicd) ); clicd.msgid = 1; buf[0]=MSG_CARD_DATA_REQ; buf[1]=0; buf[2]=0; if ( !cs_message_send(fd, &clicd, buf, 3, srv->sessionkey) ) return -1; len = cs_message_receive( fd, NULL, buf, srv->sessionkey,5000); if (len==0) { static char msg[]= "Disconnected"; srv->statmsg = msg; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: client disconnected\n"); return INVALID_SOCKET; } else if (len<0) { static char msg[]= "failed to receive card data"; srv->statmsg = msg; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: Error Recv MSG_CARD_DATA (%d)\n",len); return INVALID_SOCKET; } if (buf[0]!=MSG_CARD_DATA) { static char msg[]= "failed to receive card data"; srv->statmsg = msg; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: expected MSG_CARD_DATA\n"); return INVALID_SOCKET; } else if (len<15) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: MSG_CARD_DATA, length error (%d)\n",len); //return INVALID_SOCKET; } else { // 5. Parse CAID and PROVID(s) if ( (buf[14]<CARD_MAXPROV)&&(len>=(6+11*buf[14]))&&(buf[4]||buf[5]) ) { // CAID != 0x0000 struct cs_card_data *pcard = malloc( sizeof(struct cs_card_data) ); if (pcard) { memset(pcard, 0, sizeof(struct cs_card_data) ); pcard->caid = ((buf[4]<<8) | buf[5]); pcard->nbprov = buf[14]; pcard->uphops = 1; //pcard->sids = NULL; if (pcard->nbprov>CARD_MAXPROV) pcard->nbprov = CARD_MAXPROV; debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: caid %04x providers %d\n", pcard->caid,buf[14]); for( i=0; i<pcard->nbprov; i++ ) { pcard->prov[i] = (buf[15+11*i]<<16)|(buf[16+11*i]<<8)|buf[17+11*i]; //debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: provider %02d = %06X\n", i+1, pcard->prov[i]); } pcard->next = srv->card; srv->card = pcard; } else printf(" newcamd: failed to allocate memory\n"); } else debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: caid 0\n"); } #ifdef CLI_CSCACHE /* // Send keepalive Caching Check??? clicd.msgid = 0; clicd.sid = ('C'<<8) | 'H'; clicd.caid = 0; clicd.provid = 0; buf[0] = MSG_KEEPALIVE; buf[1] = 0; buf[2] = 0; cs_message_send(fd, &clicd, buf, 3, srv->sessionkey); */ srv->keepalive.status = GetTickCount(); srv->cscached = 0; #endif // Update Server data static char msg[]= "Connected"; srv->statmsg = msg; srv->connection.status = 1; srv->connection.time = GetTickCount(); srv->keepalive.status = 0; srv->keepalive.time = GetTickCount(); srv->busy = 0; srv->lastecmoktime = 0; srv->lastecmtime = 0; srv->lastdcwtime = 0; srv->chkrecvtime = 0; srv->msg.len = 0; srv->handle = fd; #ifdef EPOLL_ECM pipe_pointer( prg.pipe.ecm[1], PIPE_SRV_CONNECTED, srv ); #else pipe_cmd( prg.pipe.ecm[1], PIPE_SRV_CONNECTED ); #endif return 0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int cs_sendecm_srv(struct cardserver_data *cs, struct server_data *srv, ECM_DATA *ecm) { unsigned char buf[CWS_NETMSGSIZE]; struct cs_custom_data srvcd; // Custom data srv->ecm.msgid++; if (srv->ecm.msgid>0xfff) srv->ecm.msgid = 1; srvcd.msgid = srv->ecm.msgid; srvcd.sid = ecm->sid; srvcd.caid = ecm->caid; srvcd.provid = ecm->provid; memcpy( &buf[0], &ecm->ecm[0], ecm->ecmlen ); return cs_message_send( srv->handle, &srvcd, buf, ecm->ecmlen, srv->sessionkey); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void cs_srv_recvmsg(struct server_data *srv) { struct cardserver_data *cs; struct cs_custom_data srvcd; // Custom data int len; ECM_DATA *ecm; unsigned char buf[CWS_NETMSGSIZE]; if ( (srv->handle<=0)||(srv->type!=TYPE_NEWCAMD) ) return; len = cs_peekmsg( srv->handle, &srv->msg, srv->sessionkey, &srvcd, buf ); if (len==0) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server (%s:%d) read failed %d\n", srv->host->name, srv->port, len); disconnect_srv(srv); } else if (len==-1) { if (!srv->chkrecvtime) srv->chkrecvtime = GetTickCount(); else if ( (srv->chkrecvtime+300)<GetTickCount() ) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," newcamd: server (%s:%d) wrong data\n", srv->host->name, srv->port); disconnect_srv(srv); } } else if (len>0) { srv->chkrecvtime = 0; switch ( buf[0] ) { case 0x80: case 0x81: srv->lastdcwtime = GetTickCount(); if (!srv->busy) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), unknown ecm request\n",srv->host->name,srv->port); break; } srv->busy = 0; pipe_cmd( prg.pipe.ecm[1], PIPE_SRV_AVAILABLE ); if (srvcd.msgid!=srv->ecm.msgid) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), wrong message-id!!!\n",srv->host->name,srv->port); break; } pthread_mutex_lock(&prg.lockecm); //### ecm = srv->ecm.request; if (!ecm) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), ecm not found!!!\n",srv->host->name,srv->port); pthread_mutex_unlock(&prg.lockecm); //### break; } // check for ECM??? if (ecm->hash!=srv->ecm.hash) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," [!] dcw error from server (%s:%d), ecm deleted!!!\n",srv->host->name,srv->port); pthread_mutex_unlock(&prg.lockecm); //### break; } if (buf[2]==0x10) { // Check for DCW if (!acceptDCW(buf+3)) { srv->ecmerrdcw ++; pthread_mutex_unlock(&prg.lockecm); //### break; } srv->ecmok++; srv->lastecmoktime = GetTickCount()-srv->lastecmtime; srv->ecmoktime += srv->lastecmoktime; ecm_setsrvflagdcw( ecm, srv->id, ECM_SRV_REPLY_GOOD,buf+3 ); debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->cs->id)," <= cw from server (%s:%d) ch %04x:%06x:%04x (%dms)\n", srv->host->name,srv->port, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-srv->lastecmtime); if (ecm->dcwstatus!=STAT_DCW_SUCCESS) { static char msg[] = "Good dcw from Newcamd server"; ecm->statusmsg = msg; // Store ECM Answer ecm_setdcw( ecm, buf+3, DCW_SOURCE_SERVER, srv->id ); } else { //TODO: check same dcw between cards srv->ecmerrdcw ++; if ( memcmp(ecm->cw, buf+3, 16) ) debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->cs->id)," !!! different dcw from server (%s:%d)\n",srv->host->name,srv->port); } #ifdef SID_FILTER // ADD IN SID LIST cs= ecm->cs; if (cs) { cardsids_update( srv->busycard, ecm->provid, ecm->sid, 1); srv_cstatadd( srv, cs->id, 1 , srv->lastecmoktime); } #endif pthread_mutex_unlock(&prg.lockecm); //### } else { cs= ecm->cs; if ( cs && (ecm->dcwstatus!=STAT_DCW_SUCCESS) && (srv->retry<cs->option.retry.newcamd) ) { if ( (GetTickCount()-ecm->recvtime) < (cs->option.server.timeout*ecm->period) ) { srv->busy = 0; if (cs_sendecm_srv(cs, srv, ecm)>0) { srv->retry++; ecm->lastsendtime = GetTickCount(); debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->cs->id)," (RE%d) -> ecm to server (%s:%d) ch %04x:%06x:%04x\n",srv->retry,srv->host->name,srv->port,ecm->caid,ecm->provid,ecm->sid); srv->lastecmtime = GetTickCount(); srv->ecmnb++; srv->busy = 1; srv->ecm.request = ecm; pthread_mutex_unlock(&prg.lockecm); //### break; } } } ecm_setsrvflag(ecm, srv->id, ECM_SRV_REPLY_FAIL); debugf(getdbgflagpro(DBG_SERVER,0,srv->id,ecm->cs->id)," <| decode failed from server (%s:%d) ch %04x:%06x:%04x (%dms)\n", srv->host->name,srv->port, ecm->caid,ecm->provid,ecm->sid, GetTickCount()-srv->lastecmtime); #ifdef SID_FILTER // ADD IN SID LIST if (cs) { cardsids_update( srv->busycard, ecm->provid, ecm->sid, -1); srv_cstatadd( srv, cs->id, 0 , 0); } #endif pthread_mutex_unlock(&prg.lockecm); //### wakeup_sendecm(); // Wakeup ecm waiting for availabe servers } break; // ADD CARD // MSG_SERVER_2_CLIENT_REMOVECARD = 0xd4, // MSG_SERVER_2_CLIENT_ADDCARD = 0xd3, case 0xD3: if (srvcd.caid) { // CAID != 0x0000 struct cs_card_data tcard; memset(&tcard, 0, sizeof(struct cs_card_data) ); tcard.caid = srvcd.caid; tcard.nbprov = 1; tcard.prov[0] = srvcd.provid; tcard.uphops = 1; if ( tcard.uphops <= srv_sharelimits( srv, tcard.caid, srvcd.provid) ) { debugf(getdbgflag(DBG_SERVER,0,srv->id)," Mgcamd: new card (%s:%d) caid %04x provider %06X\n", srv->host->name,srv->port, tcard.caid, tcard.prov[0]); //debugf(getdbgflag(DBG_SERVER,0,srv->id)," Accepted %04x:%06x\n", tcard.caid, srvcd.provid); struct cs_card_data *card = malloc( sizeof(struct cs_card_data) ); memcpy( card, &tcard, sizeof(struct cs_card_data) ); pthread_mutex_lock(&srv->lock); //### card->next = srv->card; srv->card = card; pthread_mutex_unlock(&srv->lock); //### } //else debugf(getdbgflag(DBG_SERVER,0,srv->id)," Ignored %04x:%06x\n", tcard.caid, srvcd.provid); } break; case 0xD4: // Delete Card pthread_mutex_lock(&prg.lockecm); //### struct cs_card_data *card = srv->card; struct cs_card_data *prevcard = NULL; while (card) { if ( (card->caid==srvcd.caid)&&(card->prov[0]==srvcd.provid) ) { debugf( getdbgflag(DBG_SERVER, 0, srv->id), " Mgcamd: server (%s:%d), remove card %04x:%06x\n",srv->host->name,srv->port, srvcd.caid, srvcd.provid); if (prevcard) prevcard->next = card->next; else srv->card = card->next; //Free SIDs int s; for(s=0; s<256; s++) { struct sid_data *sid1 = card->sids[s]; while (sid1) { struct sid_data *sid = sid1; sid1 = sid1->next; free(sid); } } free(card); // check for current ecm /////XXX if (srv->busy && (srv->busycardid==k) ) ecm_setsrvflag(srv->ecm.request, srv->id, ECM_SRV_EXCLUDE); break; } prevcard = card; card = card->next; } pthread_mutex_unlock(&prg.lockecm); //### break; default: if (buf[0]==MSG_KEEPALIVE) { if (srv->keepalive.status) { #ifdef CLI_CSCACHE if ( ( srvcd.sid==(('C'<<8)|'H') ) && ( srvcd.caid==(('O'<<8)|'K') ) ) srv->cscached = 1; #endif srv->ping = GetTickCount() - srv->keepalive.time; //debugf(getdbgflag(DBG_SERVER,0,srv->id)," <- keepalive from server (%s:%d) ping %dms\n",srv->host->name,srv->port,srv->ping); srv->keepalive.status = 0; } //else debugf(getdbgflag(DBG_SERVER,0,srv->id)," <- Error keepalive from server (%s:%d)\n",srv->host->name,srv->port); } else { debugf(getdbgflag(DBG_SERVER,0,srv->id)," unknown message type '%02x' CAID:%04X PROVID:%06X from server (%s:%d)\n",buf[0],srvcd.caid,srvcd.provid,srv->host->name,srv->port); } } srv->keepalive.time = GetTickCount(); } } void cs_check_keepalive(struct server_data *srv) { struct cs_custom_data clicd; // Custom data unsigned char buf[CWS_NETMSGSIZE]; if ( (srv->handle<=0)||(srv->type!=TYPE_NEWCAMD) ) return; // Check for sending keep alive if (!srv->keepalive.status) { if ( srv->keepalive.time+(KEEPALIVE_NEWCAMD*1000) < GetTickCount() ) { buf[0] = MSG_KEEPALIVE; buf[1] = 0; buf[2] = 0; //debugf(getdbgflag(DBG_SERVER,0,srv->id)," -> keepalive to server (%s:%d)\n",srv->host->name,srv->port); if ( !cs_message_send( srv->handle, NULL, buf, 3, srv->sessionkey) ) { disconnect_srv( srv ); } else { srv->keepalive.time = GetTickCount(); srv->keepalive.status = 1; } } } else { if ( srv->keepalive.status+10000 < GetTickCount() ) { ///??? #ifdef CLI_CSCACHE // Send keepalive Caching Check??? clicd.msgid = 0; clicd.sid = ('C'<<8) | 'H'; clicd.caid = 0; clicd.provid = 0; buf[0] = MSG_KEEPALIVE; buf[1] = 0; buf[2] = 0; srv->keepalive.status = GetTickCount(); if ( !cs_message_send( srv->handle, &clicd, buf, 3, srv->sessionkey) ) disconnect_srv( srv ); #else debugf(getdbgflag(DBG_SERVER,0,srv->id)," ??? no keepalive response from server (%s:%d)\n",srv->host->name,srv->port); srv->keepalive.status = 0; #endif } } }