static void camd35_process_emm(uchar *buf, int buflen) { uint32_t keysAdded = 0; uint16_t emmlen = 0; if(!buf || buflen < 23) { return; } emmlen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; if(emmlen + 20 > buflen) { return; } cs_log_debug("ProcessEMM CAID: %X", (buf[10] << 8) | buf[11]); cs_log_hexdump("ProcessEMM: ", buf+20, emmlen); if(ProcessEMM((buf[10] << 8) | buf[11], (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15],buf+20,&keysAdded)) { cs_log_debug("EMM nok"); } else { cs_log_debug("EMM ok"); } }
static int32_t camd35_recv(uchar *buf, int32_t rs) { int32_t rc, s, n = 0, buflen = 0; for(rc = s = 0; !rc; s++) { switch(s) { case 0: if(rs < 36) { rc = -1; goto out; } break; case 1: switch(camd35_auth_client(buf)) { case 0: break; // ok case 1: rc = -2; break; // unknown user default: rc = -9; break; // error's from cs_auth() } memmove(buf, buf + 4, rs -= 4); break; case 2: aes_decrypt(&cl_aes_keys, buf, rs); if(rs != boundary(4, rs)) cs_log_debug("WARNING: packet size has wrong decryption boundary"); n = (buf[0] == 3) ? 0x34 : 0; //Fix for ECM request size > 255 (use ecm length field) if(buf[0] == 0) { buflen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; } else if(buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f) //cacheex-push { buflen = buf[1] | (buf[2] << 8); } else { buflen = buf[1]; } n = boundary(4, n + 20 + buflen); cs_log_debug("received %d bytes from client", rs); if(n < rs) cs_log_debug("ignoring %d bytes of garbage", rs - n); else if(n > rs) { rc = -3; } break; case 3: if(crc32(0, buf + 20, buflen) != b2i(4, buf + 4)) { rc = -4; cs_log_hexdump("camd35 checksum failed for packet: ", buf, rs); cs_log_debug("checksum: %X", b2i(4, buf+4)); } if(!rc) { rc = n; } break; } } out: if((rs > 0) && ((rc == -1) || (rc == -2))) { cs_log_debug("received %d bytes from client (native)", rs); } switch(rc) { case -1: cs_log("packet is too small (received %d bytes, expected at least 36 bytes)", rs); break; case -2: cs_log("unknown user"); break; case -3: cs_log("incomplete request !"); break; case -4: cs_log("checksum error (wrong password ?)"); break; } return (rc); }
static void camd35_process_ecm(uchar *buf, int buflen) { ECM_REQUEST er; uint16_t ecmlen = 0; if(!buf || buflen < 23) { return; } ecmlen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; if(ecmlen + 20 > buflen) { return; } memset(&er, 0, sizeof(ECM_REQUEST)); er.rc = E_UNHANDLED; er.ecmlen = ecmlen; er.srvid = b2i(2, buf + 8); er.caid = b2i(2, buf + 10); er.prid = b2i(4, buf + 12); cs_log_debug("ProcessECM CAID: %X", er.caid); cs_log_hexdump("ProcessECM: ", buf+20, ecmlen); if(ProcessECM(er.caid,buf+20,er.cw)) { er.rc = E_NOTFOUND; cs_log_debug("CW not found"); } else { er.rc = E_FOUND; cs_log_hexdump("Found CW: ", er.cw, 16); } if((er.rc == E_NOTFOUND || (er.rc == E_INVALID)) && !suppresscmd08) { buf[0] = 0x08; buf[1] = 2; memset(buf + 20, 0, buf[1]); buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3 } else if(er.rc == E_STOPPED) { buf[0] = 0x08; buf[1] = 2; buf[20] = 0; /* * the second Databyte should be forseen for a sleeptime in minutes * whoever knows the camd3 protocol related to CMD08 - please help! * on tests this don't work with native camd3 */ buf[21] = 0; cs_log("client stop request send"); } else { // Send CW if((er.rc < E_NOTFOUND) || (er.rc == E_FAKE)) { if(buf[0] == 3) { memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34); } buf[0]++; buf[1] = 16; memcpy(buf + 20, er.cw, buf[1]); } else { // Send old CMD44 to prevent cascading problems with older mpcs/oscam versions buf[0] = 0x44; buf[1] = 0; } } camd35_send(buf, 0); }