static void ecmwhitelist_fn(const char *token, char *value, void *setting, FILE *f) { struct s_reader *rdr = setting; if (value) { char *ptr, *ptr2, *ptr3, *saveptr1 = NULL; struct s_ecmWhitelist *tmp, *last; struct s_ecmWhitelistIdent *tmpIdent, *lastIdent; struct s_ecmWhitelistLen *tmpLen, *lastLen; for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){ for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){ for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){ add_garbage(tmpLen); } add_garbage(tmpIdent); } add_garbage(tmp); } rdr->ecmWhitelist = NULL; if(strlen(value) > 0){ saveptr1 = NULL; char *saveptr2 = NULL; for (ptr = strtok_r(value, ";", &saveptr1); ptr; ptr = strtok_r(NULL, ";", &saveptr1)) { int16_t caid = 0, len; uint32_t ident = 0; ptr2=strchr(ptr,':'); if(ptr2 != NULL){ ptr2[0] = '\0'; ++ptr2; ptr3=strchr(ptr,'@'); if(ptr3 != NULL){ ptr3[0] = '\0'; ++ptr3; ident = (uint32_t)a2i(ptr3, 6); } caid = (int16_t)dyn_word_atob(ptr); } else ptr2 = ptr; for (ptr2 = strtok_r(ptr2, ",", &saveptr2); ptr2; ptr2 = strtok_r(NULL, ",", &saveptr2)) { len = (int16_t)dyn_word_atob(ptr2); last = NULL, tmpIdent = NULL, lastIdent = NULL, tmpLen = NULL, lastLen = NULL; for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next){ last = tmp; if(tmp->caid == caid){ for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next){ lastIdent = tmpIdent; if(tmpIdent->ident == ident){ for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next){ lastLen = tmpLen; if(tmpLen->len == len) break; } break; } } } } if(tmp == NULL){ if (cs_malloc(&tmp, sizeof(struct s_ecmWhitelist))) { tmp->caid = caid; tmp->idents = NULL; tmp->next = NULL; if(last == NULL){ rdr->ecmWhitelist = tmp; } else { last->next = tmp; } } } if(tmp != NULL && tmpIdent == NULL){ if (cs_malloc(&tmpIdent, sizeof(struct s_ecmWhitelistIdent))) { tmpIdent->ident = ident; tmpIdent->lengths = NULL; tmpIdent->next = NULL; if(lastIdent == NULL){ tmp->idents = tmpIdent; } else { lastIdent->next = tmpIdent; } } } if(tmp != NULL && tmpIdent != NULL && tmpLen == NULL){ if (cs_malloc(&tmpLen, sizeof(struct s_ecmWhitelistLen))) { tmpLen->len = len; tmpLen->next = NULL; if(lastLen == NULL){ tmpIdent->lengths = tmpLen; } else { lastLen->next = tmpLen; } } } } } } return; } value = mk_t_ecmwhitelist(rdr->ecmWhitelist); if (strlen(value) > 0 || cfg.http_full_cfg) fprintf_conf(f, token, "%s\n", value); free_mk_t(value); }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = 0; int mode, ret; ut64 off = a->pc; mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; if (cd && mode != omode) { cs_close (&cd); cd = 0; } op->size = 0; omode = mode; if (cd == 0) { ret = cs_open (CS_ARCH_X86, mode, &cd); if (ret) return 0; } if (a->features && *a->features) { cs_option (cd, CS_OPT_DETAIL, CS_OPT_ON); } else { cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); } if (a->syntax == R_ASM_SYNTAX_ATT) { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); } else { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); } op->size = 1; #if USE_ITER_API { size_t size = len; if (insn == NULL) insn = cs_malloc (cd); insn->size = 1; memset (insn, 0, insn->size); n = cs_disasm_iter (cd, (const uint8_t**)&buf, &size, (uint64_t*)&off, insn); } #else n = cs_disasm (cd, (const ut8*)buf, len, off, 1, &insn); #endif op->size = 0; if (a->features && *a->features) { if (!check_features (a, insn)) { op->size = insn->size; strcpy (op->buf_asm, "illegal"); } } if (op->size==0 && n>0 && insn->size>0) { char *ptrstr; op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); ptrstr = strstr (op->buf_asm, "ptr "); if (ptrstr) { memmove (ptrstr, ptrstr+4, strlen (ptrstr+4)+1); } } if (a->syntax == R_ASM_SYNTAX_JZ) { if (!strncmp (op->buf_asm, "je ", 3)) { memcpy (op->buf_asm, "jz", 2); } else if (!strncmp (op->buf_asm, "jne ", 4)) { memcpy (op->buf_asm, "jnz", 3); } } #if USE_ITER_API /* do nothing because it should be allocated once and freed in the_end */ #else cs_free (insn, n); insn = NULL; #endif return op->size; }
int32_t coolapi_set_filter (int32_t fd, int32_t num, int32_t pid, uchar * flt, uchar * mask, int32_t type) { dmx_t * dmx = find_demux(fd, 0); if(!dmx) { cs_debug_mask(D_DVBAPI, "dmx is NULL!"); return -1; } int32_t result, channel_found=0; void * channel = NULL; if (ll_count(ll_cool_chanhandle) > 0) { LL_ITER itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while ((handle_item=ll_iter_next(&itr))) { if (handle_item->demux_index == dmx->demux_index && handle_item->pid == pid) { channel = handle_item->channel; channel_found=1; break; } } } if (!channel) { buffer_open_arg_t bufarg; int32_t uBufferSize = 8256; memset(&bufarg, 0, sizeof(bufarg)); bufarg.type = 3; bufarg.size = uBufferSize; bufarg.unknown3 = (uBufferSize * 7) / 8; result = cnxt_cbuf_open(&dmx->buffer1, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); bufarg.type = 0; result = cnxt_cbuf_open(&dmx->buffer2, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); channel_open_arg_t chanarg; memset(&chanarg, 0, sizeof(channel_open_arg_t)); chanarg.type = 4; result = cnxt_dmx_channel_open(dmx->device, &dmx->channel, &chanarg, dmx_callback, dmx); coolapi_check_error("cnxt_dmx_channel_open", result); result = cnxt_dmx_set_channel_buffer(dmx->channel, 0, dmx->buffer1); coolapi_check_error("cnxt_dmx_set_channel_buffer", result); result = cnxt_dmx_channel_attach(dmx->channel, 0xB, 0, dmx->buffer2); coolapi_check_error("cnxt_dmx_channel_attach", result); result = cnxt_cbuf_attach(dmx->buffer2, 2, dmx->channel); coolapi_check_error("cnxt_cbuf_attach", result); result = cnxt_dmx_set_channel_pid(dmx->channel, pid); coolapi_check_error("cnxt_dmx_set_channel_pid", result); result = cnxt_cbuf_flush (dmx->buffer1, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_flush (dmx->buffer2, 0); coolapi_check_error("cnxt_cbuf_flush", result); S_COOL_CHANHANDLE *handle_item; if (cs_malloc(&handle_item,sizeof(S_COOL_CHANHANDLE))) { handle_item->pid = pid; handle_item->channel = dmx->channel; handle_item->buffer1 = dmx->buffer1; handle_item->buffer2 = dmx->buffer2; handle_item->demux_index = dmx->demux_index; ll_append(ll_cool_chanhandle, handle_item); } cs_debug_mask(D_DVBAPI, "opened new channel %x", (int32_t) dmx->channel); } else { channel_found=1; dmx->channel = channel; dmx->buffer1 = NULL; dmx->buffer2 = NULL; } cs_debug_mask(D_DVBAPI, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x", fd, dmx->demux_index, (int32_t) dmx->channel, num, pid, flt[0], mask[0]); pthread_mutex_lock(&dmx->mutex); filter_set_t filter; dmx->filter_num = num; dmx->pid = pid; dmx->type = type; memset(&filter, 0, sizeof(filter)); filter.length = 12; memcpy(filter.filter, flt, 16); memcpy(filter.mask, mask, 16); result = cnxt_dmx_open_filter(dmx->device, &dmx->filter); coolapi_check_error("cnxt_dmx_open_filter", result); result = cnxt_dmx_set_filter(dmx->filter, &filter, NULL); coolapi_check_error("cnxt_dmx_set_filter", result); result = cnxt_dmx_channel_attach_filter(dmx->channel, dmx->filter); coolapi_check_error("cnxt_dmx_channel_attach_filter", result); if (channel_found) { result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); } result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); pthread_mutex_unlock(&dmx->mutex); S_COOL_FILTER *filter_item; if (cs_malloc(&filter_item,sizeof(S_COOL_FILTER))) { // fill filter item filter_item->fd = fd; filter_item->pid = pid; filter_item->channel = (int32_t) dmx->channel; memcpy(filter_item->filter16, flt, 16); memcpy(filter_item->mask16, mask, 16); //add filter item ll_append(ll_cool_filter, filter_item); } return 0; }
void cc_cacheex_push_in(struct s_client *cl, uchar *buf) { struct cc_data *cc = cl->cc; ECM_REQUEST *er; if(!cc) { return; } if(cl->reader) { cl->reader->last_s = cl->reader->last_g = time((time_t *)0); } if(cl) { cl->last = time(NULL); } int8_t rc = buf[14]; if(rc != E_FOUND && rc != E_UNHANDLED) //Maybe later we could support other rcs { return; } uint16_t size = buf[12] | (buf[13] << 8); if(size != sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) { cs_log_dbg(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl)); return; } if(!(er = get_ecmtask())) { return; } er->caid = b2i(2, buf + 0); er->prid = b2i(4, buf + 2); er->srvid = b2i(2, buf + 10); er->ecm[0] = buf[19]!=0x80 && buf[19]!=0x81 ? 0 : buf[19]; //odd/even byte, usefull to send it over CSP and to check cw for swapping er->rc = rc; er->ecmlen = 0; if(buf[18]) { if(buf[18] & (0x01 << 7)) { er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime er->cwc_next_cw_cycle = 1; } else { er->cwc_cycletime = buf[18]; er->cwc_next_cw_cycle = 0; } } if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2) { if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode) { cl->account->cwc_info++; } else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode)) { cl->cwc_info++; } cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X:%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid); } uint8_t *ofs = buf + 20; //Read ecmd5 memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16 ofs += sizeof(er->ecmd5); if(!check_cacheex_filter(cl, er)) { return; } //Read csp_hash: er->csp_hash = ntohl(b2i(4, ofs)); ofs += 4; //Read cw: memcpy(er->cw, ofs, sizeof(er->cw)); //16 ofs += sizeof(er->cw); //Read lastnode count: uint8_t count = *ofs; ofs++; //check max nodes: if(count > cacheex_maxhop(cl)) { cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl)); NULLFREE(er); return; } cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl)); //Read lastnodes: uint8_t *data; if (er){ er->csp_lastnodes = ll_create("csp_lastnodes"); } while(count) { if(!cs_malloc(&data, 8)) { break; } memcpy(data, ofs, 8); ofs += 8; ll_append(er->csp_lastnodes, data); count--; cs_log_dbg(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl)); } //for compatibility: add peer node if no node received: if(!ll_count(er->csp_lastnodes)) { if(!cs_malloc(&data, 8)) { return; } memcpy(data, cc->peer_node_id, 8); ll_append(er->csp_lastnodes, data); cs_log_dbg(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data)); } cacheex_add_to_cache(cl, er); }
//Todo #ifdef CCCAM int32_t init_provid(void) { FILE *fp = open_config_file(cs_provid); if(!fp) { return 0; } int32_t nr; char *payload, *saveptr1 = NULL, *token; if(!cs_malloc(&token, MAXLINESIZE)) { return 0; } static struct s_provid *provid = (struct s_provid *)0; nr = 0; while(fgets(token, MAXLINESIZE, fp)) { int32_t l; void *ptr; char *tmp, *providasc; tmp = trim(token); if(tmp[0] == '#') { continue; } if((l = strlen(tmp)) < 11) { continue; } if(!(payload = strchr(token, '|'))) { continue; } if(!(providasc = strchr(token, ':'))) { continue; } *payload++ = '\0'; if(!cs_malloc(&ptr, sizeof(struct s_provid))) { NULLFREE(token); fclose(fp); return (1); } if(provid) { provid->next = ptr; } else { cfg.provid = ptr; } provid = ptr; int32_t i; char *ptr1; for(i = 0, ptr1 = strtok_r(payload, "|", &saveptr1); ptr1; ptr1 = strtok_r(NULL, "|", &saveptr1), i++) { switch(i) { case 0: cs_strncpy(provid->prov, trim(ptr1), sizeof(provid->prov)); break; case 1: cs_strncpy(provid->sat, trim(ptr1), sizeof(provid->sat)); break; case 2: cs_strncpy(provid->lang, trim(ptr1), sizeof(provid->lang)); break; } } *providasc++ = '\0'; provid->provid = a2i(providasc, 3); provid->caid = a2i(token, 3); nr++; } NULLFREE(token); fclose(fp); if(nr > 0) { cs_log("%d provid's loaded", nr); } return (0); }
bool NetBase::CheckIn() { // check for incoming packets SOCKADDR_IN addr; memset (&addr, 0, sizeof(SOCKADDR_IN)); socklen_t len = sizeof(SOCKADDR_IN); if (!input_buffer) { input_buffer = (char*) cs_malloc(MAXPACKETSIZE); if (!input_buffer) { Error2("Failed to cs_malloc %d bytes for packet buffer!\n",MAXPACKETSIZE); return false; } } // Connection must be initialized! CS_ASSERT(ready); int packetlen = RecvFrom (&addr, &len, (void*) input_buffer, MAXPACKETSIZE); if (packetlen <= 0) { return false; } // Identify the connection Connection* connection = GetConnByIP(&addr); // Extract the netpacket from the buffer and prep for use locally. psNetPacket *bufpacket = psNetPacket::NetPacketFromBuffer(input_buffer,packetlen); if (bufpacket==NULL) { char addrText[INET_ADDRSTRLEN]; //for win32 for now only inet_ntoa as inet_ntop wasn't supported till vista. //it has the same degree of compatibility of the previous code and it's supported till win2000 #ifdef WIN32 strncpy(addrText, inet_ntoa(addr.sin_addr), INET_ADDRSTRLEN); #else //there was a failure in conversion if null if(!inet_ntop(addr.sin_family,&addr.sin_addr, addrText, sizeof(addrText))) { strncpy(addrText, "UNKNOWN", INET_ADDRSTRLEN); } #endif // The data received was too small to make a full packet. if (connection) { Debug4(LOG_NET, connection->clientnum, "Too short packet received from client %d (IP: %s) (%d bytes)", connection->clientnum, addrText, packetlen); } else { Debug3(LOG_NET, 0, "Too short packet received from IP address %s. (%d bytes) No existing connection from this IP.", addrText, packetlen); } return true; // Continue processing more packets if available } input_buffer = NULL; //input_buffer now hold by the bufpacket pointer. // Endian correction bufpacket->UnmarshallEndian(); // Check for too-big packets - no harm in processing them, but probably a bug somewhere if (bufpacket->GetPacketSize() < static_cast<unsigned int>(packetlen)) { char addrText[INET_ADDRSTRLEN]; //for win32 for now only inet_ntoa as inet_ntop wasn't supported till vista. //it has the same degree of compatibility of the previous code and it's supported till win2000 #ifdef WIN32 strncpy(addrText, inet_ntoa(addr.sin_addr), INET_ADDRSTRLEN); #else //there was a failure in conversion if null if(!inet_ntop(addr.sin_family,&addr.sin_addr, addrText, sizeof(addrText))) { strncpy(addrText, "UNKNOWN", INET_ADDRSTRLEN); } #endif if (connection) { Debug5(LOG_NET, connection->clientnum, "Too long packet received from client %d (IP: %s) (%d bytes received, header reports %zu bytes)", connection->clientnum, addrText, packetlen, bufpacket->GetPacketSize()); } else { Debug4(LOG_NET, 0,"Too long packet received from IP address %s. (%d bytes received, header reports %zu bytes) No existing connection from this IP.", addrText, packetlen, bufpacket->GetPacketSize()); } } //Create new net packet entry and transfer ownership of bufpacket to pkt. csRef<psNetPacketEntry> pkt; pkt.AttachNew(new psNetPacketEntry( bufpacket, connection ? connection->clientnum : 0, packetlen)); if(TEST_PACKETLOSS > 0.0 && randomgen->Get() < TEST_PACKETLOSS) { psNetPacket* packet = pkt->packet; int type = 0; if (packet->offset == 0) { psMessageBytes* msg = (psMessageBytes*) packet->data; type = msg->type; } Error3("Packet simulated lost. Type %s ID %d.\n", type == 0 ? "Fragment" : (const char *) GetMsgTypeName(type), pkt->packet->pktid); return true; } // ACK packets can get eaten by HandleAck if (HandleAck(pkt, connection, &addr)) { return true; } // printf("Got packet with sequence %d.\n", pkt->packet->GetSequence()); // // Check for doubled packets and drop them if (pkt->packet->pktid != 0) { if (connection && CheckDoublePackets (connection, pkt)) { #ifdef PACKETDEBUG Debug2(LOG_NET,0,"Dropping doubled packet (ID %d)\n", pkt->packet->pktid); #endif return true; } } #ifdef PACKETDEBUG Debug7(LOG_NET,0,"Received Pkt, ID: %d, offset %d, from %d size %d (actual %d) flags %d\n", pkt->packet->pktid, pkt->packet->offset, pkt->clientnum, pkt->packet->pktsize,packetlen, pkt->packet->flags); #endif /** * Now either send this packet to BuildMessage, or loop through * subpackets if they are merged. */ csRef<psNetPacketEntry> splitpacket = pkt; psNetPacket *packetdata = NULL; do { splitpacket = pkt->GetNextPacket(packetdata); if (splitpacket) BuildMessage(splitpacket, connection, &addr); } while (packetdata); return true; }
static void ac_load_config(void) { FILE *fp = open_config_file(cs_ac); if(!fp) { return; } int32_t nr; char *saveptr1 = NULL, *token; if(!cs_malloc(&token, MAXLINESIZE)) { return; } struct s_cpmap *cur_cpmap, *first_cpmap = NULL, *last_cpmap = NULL; for(nr = 0; fgets(token, MAXLINESIZE, fp);) { int32_t i, skip; uint16_t caid, sid, chid, dwtime; uint32_t provid; char *ptr, *ptr1; if(strlen(token) < 4) { continue; } caid = sid = chid = dwtime = 0; provid = 0; skip = 0; ptr1 = 0; for(i = 0, ptr = strtok_r(token, "=", &saveptr1); (i < 2) && (ptr); ptr = strtok_r(NULL, "=", &saveptr1), i++) { trim(ptr); if(*ptr == ';' || *ptr == '#' || *ptr == '-') { skip = 1; break; } switch(i) { case 0: ptr1 = ptr; break; case 1: dwtime = atoi(ptr); break; } } if(!skip) { for(i = 0, ptr = strtok_r(ptr1, ":", &saveptr1); (i < 4) && (ptr); ptr = strtok_r(NULL, ":", &saveptr1), i++) { trim(ptr); switch(i) { case 0: if(*ptr == '*') { caid = 0; } else { caid = a2i(ptr, 4); } break; case 1: if(*ptr == '*') { provid = 0; } else { provid = a2i(ptr, 6); } break; case 2: if(*ptr == '*') { sid = 0; } else { sid = a2i(ptr, 4); } break; case 3: if(*ptr == '*') { chid = 0; } else { chid = a2i(ptr, 4); } break; } } if(!cs_malloc(&cur_cpmap, sizeof(struct s_cpmap))) { for(cur_cpmap = first_cpmap; cur_cpmap;) { last_cpmap = cur_cpmap; cur_cpmap = cur_cpmap->next; NULLFREE(last_cpmap); } NULLFREE(token); return; } if(last_cpmap) { last_cpmap->next = cur_cpmap; } else { first_cpmap = cur_cpmap; } last_cpmap = cur_cpmap; cur_cpmap->caid = caid; cur_cpmap->provid = provid; cur_cpmap->sid = sid; cur_cpmap->chid = chid; cur_cpmap->dwtime = dwtime; cur_cpmap->next = 0; cs_log_dbg(D_CLIENT, "nr=%d, caid=%04X, provid=%06X, sid=%04X, chid=%04X, dwtime=%d", nr, caid, provid, sid, chid, dwtime); nr++; } } NULLFREE(token); fclose(fp); last_cpmap = cfg.cpmap; cfg.cpmap = first_cpmap; for(cur_cpmap = last_cpmap; cur_cpmap; cur_cpmap = cur_cpmap->next) { add_garbage(cur_cpmap); } //cs_log("%d lengths for caid guessing loaded", nr); return; }
jump_block* init_jump_block (jump_block* to_init, unsigned int start_addr, unsigned int stop_addr) { to_init->instructions = NULL; to_init->calls = NULL; to_init->conditional_jumps = NULL; to_init->flags = next_flags; next_flags = 0; to_init->next = NULL; //Locals to cut down on dereference operators; this code was a disaster the first time around with no locals size_t size = file_size; int num_instructions = 0; int num_calls = 0; int num_conditional_jumps = 0; unsigned long long relative_address = 0; unsigned int current_addr = start_addr; uint8_t* current = file_buf + addr_to_index (current_addr); unsigned int next_addr; cs_insn* instruction = cs_malloc (handle); to_init->start = start_addr; do { num_instructions ++; //Dynamic memory allocation stuff here if (num_instructions - 1) { if (num_instructions * sizeof (cs_insn) > to_init->instructions_buf_size) { to_init->instructions_buf_size *= 2; //Just double the buffer; I'd rather allocate too much than reallocate memory every single iteration to_init->instructions = (cs_insn*)realloc (to_init->instructions, to_init->instructions_buf_size); } } else { to_init->instructions_buf_size = 256 * sizeof (cs_insn); //My memory allocator screams at me for numbers that aren't a multiple of 8 to_init->instructions = (cs_insn*)malloc (to_init->instructions_buf_size); } //Partially disassemble the instruction into machine readable format cs_disasm_iter (handle, (const uint8_t **)¤t, &file_size, (uint64_t*)&relative_address, instruction); to_init->instructions [num_instructions-1] = *instruction; to_init->instructions [num_instructions-1].detail = (cs_detail*)malloc (sizeof(cs_detail)); *(to_init->instructions [num_instructions-1].detail) = *(instruction->detail); current_addr = index_to_addr ((char*)current - file_buf); //Identify references to conditional jump blocks and function calls for later disassembly. if (instruction->detail->x86.op_count && instruction->detail->x86.operands [0].type > X86_OP_REG) //Please don't go chasing rax... { //Keep track of calls if (instruction->id == X86_INS_CALL) { num_calls ++; //More dynamic memory allocation stuff here if (num_calls - 1) { if (num_calls * sizeof (unsigned int) > to_init->calls_buf_size) { to_init->calls_buf_size *= 2; to_init->calls = realloc (to_init->calls, to_init->calls_buf_size); } } else { to_init->calls_buf_size = 8 * sizeof (unsigned int); to_init->calls = malloc (to_init->calls_buf_size); } //Add operand address to call buffer to_init->calls [num_calls-1] = relative_insn (instruction, current_addr); } } //Keep track of how many times we've seen the instruction "push %ebp". One too many and we've started on the adjacent function. if ((instruction->id >= X86_INS_PUSH && instruction->id <= X86_INS_PUSHFQ) && (instruction->detail->x86.operands [0].reg == X86_REG_EBP || instruction->detail->x86.operands [0].reg == X86_REG_RBP)) num_push_ebp ++; if (current_addr > stop_addr) //If we're outside the text section, we should be done. num_push_ebp = 2; //Stop disassembly of jump block at next unconditional jump or call } while (instruction->mnemonic [0] != 'j' && num_push_ebp != 2); //Jump block ends on jump or return //Synchronize the jump block with locals to_init->end = current_addr; to_init->num_conditional_jumps = num_conditional_jumps; to_init->num_calls = num_calls; to_init->num_instructions = num_instructions; if (instruction->id >= X86_INS_JAE && instruction->id <= X86_INS_JS && instruction->id != X86_INS_JMP) { if (relative_insn (instruction, current_addr) < current_addr - instruction->size) { to_init->flags |= IS_LOOP; next_flags |= IS_AFTER_LOOP; } } cs_free (instruction, 1); //Print jump block start address; uncomment for debugging information //printf ("%p\n", to_init->start); return to_init; //Convenient to return the to_init param so we can chain function calls like "example (init_jump_block (malloc (sizeof (jump_block)), some_addr, block))" }
static int32_t dre_card_init(struct s_reader *reader, ATR *newatr) { get_atr; def_resp; uchar ua[] = { 0x43, 0x15 }; // get serial number (UA) uchar providers[] = { 0x49, 0x15 }; // get providers int32_t i; char *card; char tmp[9]; if((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12) || ( ((atr[4] != 0xca) || (atr[5] != 0x07)) && ((atr[4] != 0x01) || (atr[5] != 0x01)) )) { return ERROR; } if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data))) { return ERROR; } struct dre_data *csystem_data = reader->csystem_data; csystem_data->provider = atr[6]; uchar checksum = xor(atr + 1, 6); if(checksum != atr[7]) { rdr_log(reader, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]); } switch(atr[6]) { case 0x11: card = "Tricolor Centr"; reader->caid = 0x4ae1; break; //59 type card = MSP (74 type = ATMEL) case 0x12: card = "Cable TV"; reader->caid = 0x4ae1; //TODO not sure about this one break; case 0x14: card = "Tricolor Syberia / Platforma HD new"; reader->caid = 0x4ae1; break; //59 type card case 0x15: card = "Platforma HD / DW old"; reader->caid = 0x4ae1; break; //59 type card default: card = "Unknown"; reader->caid = 0x4ae1; break; } memset(reader->prid, 0x00, 8); static const uchar cmd30[] = { 0x30, 0x81, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x08, 0x09, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x00 }; dre_cmd(cmd30); //unknown command, generates error on card 0x11 and 0x14 /* response: 59 03 E2 E3 FE 48 */ uchar cmd54[] = { 0x54, 0x14 }; // geocode cmd54[1] = csystem_data->provider; uchar geocode = 0; if((dre_cmd(cmd54))) //error would not be fatal, like on 0x11 cards { geocode = cta_res[3]; } providers[1] = csystem_data->provider; if(!(dre_cmd(providers))) { return ERROR; } //fatal error if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; } uchar provname[128]; for(i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++) { provname[i] = cta_res[6 + i]; if(provname[i] == 0x00) { break; } } int32_t major_version = cta_res[3]; int32_t minor_version = cta_res[4]; ua[1] = csystem_data->provider; dre_cmd(ua); //error would not be fatal int32_t hexlength = cta_res[1] - 2; //discard first and last byte, last byte is always checksum, first is answer code reader->hexserial[0] = 0; reader->hexserial[1] = 0; memcpy(reader->hexserial + 2, cta_res + 3, hexlength); int32_t low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608; int32_t dre_chksum = 0; uchar buf[32]; snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider - 16, major_version + 1, low_dre_id); for(i = 0; i < 32; i++) { if(buf[i] == 0x00) { break; } dre_chksum += buf[i] - 48; } rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i", reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider - 16, major_version + 1, low_dre_id, geocode, card, major_version, minor_version); rdr_log(reader, "Provider name:%s.", provname); memset(reader->sa, 0, sizeof(reader->sa)); memcpy(reader->sa[0], reader->hexserial + 2, 1); //copy first byte of unique address also in shared address, because we dont know what it is... rdr_log_sensitive(reader, "SA = %02X%02X%02X%02X, UA = {%s}", reader->sa[0][0], reader->sa[0][1], reader->sa[0][2], reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp))); reader->nprov = 1; if(!dre_set_provider_info(reader)) { return ERROR; } //fatal error rdr_log(reader, "ready for requests"); return OK; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; #if USE_ITER_API static #endif cs_insn *insn = NULL; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret = cs_open (CS_ARCH_X86, mode, &handle); int regsz = 4; if (ret != CS_ERR_OK) { return 0; } switch (a->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: case 32: regsz = 4; break; } memset (op, '\0', sizeof (RAnalOp)); op->cycles = 1; // aprox op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->src[0] = NULL; op->src[1] = NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next #if USE_ITER_API { ut64 naddr = addr; size_t size = len; if (insn == NULL) insn = cs_malloc (handle); n = cs_disasm_iter (handle, (const uint8_t**)&buf, &size, (uint64_t*)&naddr, insn); } #else n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); #endif struct Getarg gop = { .handle = handle, .insn = insn, .bits = a->bits }; if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp"; op->size = insn->size; op->family = 0; op->prefix = 0; switch (insn->detail->x86.prefix[0]) { case X86_PREFIX_REPNE: op->prefix |= R_ANAL_OP_PREFIX_REPNE; break; case X86_PREFIX_REP: op->prefix |= R_ANAL_OP_PREFIX_REP; break; case X86_PREFIX_LOCK: op->prefix |= R_ANAL_OP_PREFIX_LOCK; break; } switch (insn->id) { case X86_INS_FNOP: case X86_INS_NOP: case X86_INS_PAUSE: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ","); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_FBLD: case X86_INS_FBSTP: case X86_INS_FCOMPP: case X86_INS_FDECSTP: case X86_INS_FEMMS: case X86_INS_FFREE: case X86_INS_FICOM: case X86_INS_FICOMP: case X86_INS_FINCSTP: case X86_INS_FNCLEX: case X86_INS_FNINIT: case X86_INS_FNSTCW: case X86_INS_FNSTSW: case X86_INS_FPATAN: case X86_INS_FPREM: case X86_INS_FPREM1: case X86_INS_FPTAN: #if CS_API_MAJOR >=4 case X86_INS_FFREEP: #endif case X86_INS_FRNDINT: case X86_INS_FRSTOR: case X86_INS_FNSAVE: case X86_INS_FSCALE: case X86_INS_FSETPM: case X86_INS_FSINCOS: case X86_INS_FNSTENV: case X86_INS_FXAM: case X86_INS_FXSAVE: case X86_INS_FXSAVE64: case X86_INS_FXTRACT: case X86_INS_FYL2X: case X86_INS_FYL2XP1: case X86_INS_FISTTP: case X86_INS_FSQRT: case X86_INS_FXCH: case X86_INS_FTST: case X86_INS_FUCOMPI: case X86_INS_FUCOMI: case X86_INS_FUCOMPP: case X86_INS_FUCOMP: case X86_INS_FUCOM: op->type = R_ANAL_OP_TYPE_SUB; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FLDCW: case X86_INS_FLDENV: case X86_INS_FLDL2E: case X86_INS_FLDL2T: case X86_INS_FLDLG2: case X86_INS_FLDLN2: case X86_INS_FLDPI: case X86_INS_FLDZ: case X86_INS_FLD1: case X86_INS_FLD: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FIST: case X86_INS_FISTP: case X86_INS_FST: case X86_INS_FSTP: case X86_INS_FSTPNCE: case X86_INS_FXRSTOR: case X86_INS_FXRSTOR64: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FDIV: case X86_INS_FIDIV: case X86_INS_FDIVP: case X86_INS_FDIVR: case X86_INS_FIDIVR: case X86_INS_FDIVRP: case X86_INS_FSUBR: case X86_INS_FISUBR: case X86_INS_FSUBRP: case X86_INS_FSUB: case X86_INS_FISUB: case X86_INS_FSUBP: op->type = R_ANAL_OP_TYPE_SUB; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FMUL: case X86_INS_FIMUL: case X86_INS_FMULP: op->type = R_ANAL_OP_TYPE_MUL; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_CLI: case X86_INS_STI: case X86_INS_CLC: case X86_INS_STC: op->type = R_ANAL_OP_TYPE_SWI; op->family = R_ANAL_OP_FAMILY_PRIV; break; // cmov case X86_INS_SETNE: case X86_INS_SETNO: case X86_INS_SETNP: case X86_INS_SETNS: case X86_INS_SETO: case X86_INS_SETP: case X86_INS_SETS: case X86_INS_SETL: case X86_INS_SETLE: case X86_INS_SETB: case X86_INS_SETG: case X86_INS_SETAE: case X86_INS_SETA: case X86_INS_SETBE: case X86_INS_SETE: case X86_INS_SETGE: op->type = R_ANAL_OP_TYPE_CMOV; op->family = 0; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); switch (insn->id) { case X86_INS_SETE: esilprintf (op, "zf,%s,=", dst); break; case X86_INS_SETNE: esilprintf (op, "zf,!,%s,=", dst); break; case X86_INS_SETO: esilprintf (op, "of,%s,=", dst); break; case X86_INS_SETNO: esilprintf (op, "of,!,%s,=", dst); break; case X86_INS_SETP: esilprintf (op, "pf,%s,=", dst); break; case X86_INS_SETNP: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETS: esilprintf (op, "sf,%s,=", dst); break; case X86_INS_SETNS: esilprintf (op, "sf,!,%s,=", dst); break; case X86_INS_SETB: esilprintf (op, "cf,%s,=", dst); break; case X86_INS_SETAE: esilprintf (op, "cf,!,%s,=", dst); break; /* TODO */ #if 0 SETLE/SETNG Sets the byte in the operand to 1 if the Zero Flag is set or the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. SETBE/SETNA Sets the byte in the operand to 1 if the Carry Flag or the Zero Flag is set, otherwise sets the operand to 0. SETL/SETNGE Sets the byte in the operand to 1 if the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. case X86_INS_SETL: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETLE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETG: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETA: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETBE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETGE: esilprintf (op, "pf,!,%s,=", dst); break; break; #endif } free (dst); } break; // cmov case X86_INS_CMOVA: case X86_INS_CMOVAE: case X86_INS_CMOVB: case X86_INS_CMOVBE: case X86_INS_FCMOVBE: case X86_INS_FCMOVB: case X86_INS_CMOVE: case X86_INS_FCMOVE: case X86_INS_CMOVG: case X86_INS_CMOVGE: case X86_INS_CMOVL: case X86_INS_CMOVLE: case X86_INS_FCMOVNBE: case X86_INS_FCMOVNB: case X86_INS_CMOVNE: case X86_INS_FCMOVNE: case X86_INS_CMOVNO: case X86_INS_CMOVNP: case X86_INS_FCMOVNU: case X86_INS_CMOVNS: case X86_INS_CMOVO: case X86_INS_CMOVP: case X86_INS_FCMOVU: case X86_INS_CMOVS: // mov case X86_INS_MOV: case X86_INS_MOVAPS: case X86_INS_MOVAPD: case X86_INS_MOVZX: case X86_INS_MOVUPS: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSS: case X86_INS_MOVSX: case X86_INS_MOVSXD: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: { op->type = R_ANAL_OP_TYPE_MOV; op->ptr = UT64_MAX; switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->ptr = UT64_MAX; op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } else { op->ptr = UT64_MAX; } if (a->decode) { if (op->prefix & R_ANAL_OP_PREFIX_REP) { int width = INSOP(0).size; const char *src = cs_reg_name(handle, INSOP(1).mem.base); const char *dst = cs_reg_name(handle, INSOP(0).mem.base); const char *counter = (a->bits==16)?"cx": (a->bits==32)?"ecx":"rcx"; esilprintf (op, "%s,!,?{,BREAK,},%s,DUP,%s,DUP,"\ "%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\ "df,!,?{,%d,%s,+=,%d,%s,+=,},%s,--=,%s," \ "?{,8,GOTO,},%s,=,%s,=", counter, src, dst, src, width, dst, width, width, src, width, dst, width, src, width, dst, counter, counter, dst, src); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } } break; default: if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, dst); free (src); free (dst); } break; } if (op->refptr<1 || op->ptr == UT64_MAX) { switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } } } break; case X86_INS_SHL: case X86_INS_SHLD: case X86_INS_SHLX: op->type = R_ANAL_OP_TYPE_SHL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAR: case X86_INS_SARX: op->type = R_ANAL_OP_TYPE_SAR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, ">>"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAL: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SALC: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { esilprintf (op, "$z,DUP,zf,=,al,="); } break; case X86_INS_SHR: case X86_INS_SHRD: case X86_INS_SHRX: op->type = R_ANAL_OP_TYPE_SHR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,>>=,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_CMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: if (insn->id == X86_INS_TEST) { op->type = R_ANAL_OP_TYPE_ACMP; //compare via and if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "0,%s,%s,&,==,$z,zf,=,$p,pf,=,$s,sf,=,0,cf,=,0,of,=", src, dst); free (src); free (dst); } } else { op->type = R_ANAL_OP_TYPE_CMP; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,==,$z,zf,=,$b%d,cf,=,$p,pf,=,$s,sf,=", src, dst, (INSOP(0).size*8)); free (src); free (dst); } } switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } op->ptr = INSOP(1).imm; break; default: switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; case X86_OP_IMM: op->ptr = INSOP(1).imm; break; default: break; } break; } break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 1, 2, NULL); esilprintf (op, "%s,%s,=", dst, src); free (src); free (dst); } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; switch (INSOP(1).mem.base) { case X86_REG_RIP: op->ptr += addr + op->size; break; case X86_REG_RBP: case X86_REG_EBP: op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; break; default: /* unhandled */ break; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%d,%s,-=,%s,%s,=[%d]", rs, sp, dst, sp, rs); free (dst); } switch (INSOP(0).type) { case X86_OP_IMM: op->ptr = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_PUSH; break; default: op->type = R_ANAL_OP_TYPE_UPUSH; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case X86_INS_LEAVE: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { esilprintf (op, "%s,%s,=,%s,[%d],%s,=,%d,%s,+=", bp, sp, sp, rs, bp, rs, sp); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_POP: case X86_INS_POPF: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, dst, rs, sp); free (dst); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_RETFQ: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_INT3: if (a->decode) esilprintf (op, "3,$"); op->type = R_ANAL_OP_TYPE_TRAP; // TRAP break; case X86_INS_INT1: if (a->decode) esilprintf (op, "1,$"); op->type = R_ANAL_OP_TYPE_SWI; // TRAP break; case X86_INS_INT: if (a->decode) esilprintf (op, "%d,$", R_ABS((int)INSOP(0).imm)); op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_INTO: case X86_INS_VMCALL: case X86_INS_VMMCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JRCXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: case X86_INS_LOOP: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; if (a->decode) { char *dst = getarg (&gop, 0, 2, NULL); switch (insn->id) { case X86_INS_JL: esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JLE: esilprintf (op, "of,sf,^,zf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JA: esilprintf (op, "cf,zf,|,!,?{,%s,%s,=,}",dst, pc); break; case X86_INS_JAE: esilprintf (op, "cf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JB: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JO: esilprintf (op, "of,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNO: esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JE: esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JGE: esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNE: esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JG: esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JS: esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNS: esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JP: esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNP: esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JBE: esilprintf (op, "zf,cf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JCXZ: esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JECXZ: esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JRCXZ: esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc); break; } free (dst); } break; case X86_INS_CALL: case X86_INS_LCALL: switch (INSOP(0).type) { case X86_OP_IMM: op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; if (INSOP(0).mem.base == 0) { op->ptr = INSOP(0).mem.disp; } break; default: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; break; } if (a->decode) { char* arg = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s," "%d,%s,-=,%s," "=[]," "%s,%s,=", pc, rs, sp, sp, arg, pc); free (arg); } break; case X86_INS_JMP: case X86_INS_LJMP: if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, pc); free (src); } // TODO: what if UJMP? switch (INSOP(0).type) { case X86_OP_IMM: op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UJMP; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr = INSOP(0).mem.disp; op->ptr += addr + insn->size; op->refptr = 8; } else { cs_x86_op in = INSOP(0); if (in.mem.index == 0 && in.mem.base == 0 && in.mem.scale == 1) { op->type = R_ANAL_OP_TYPE_UJMP; op->ptr = in.mem.disp; if (a->decode) { esilprintf (op, "0x%"PFMT64x",[],%s,=", op->ptr, pc); } } } break; case X86_OP_REG: case X86_OP_FP: default: // other? op->type = R_ANAL_OP_TYPE_UJMP; break; } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_XORPS: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "^"); esilprintf (op, "%s,%s,$z,zf,=,$p,pf,=,0,cf,=,0,of,=,$s,sf,=", src, dst); free (src); free (dst); } break; case X86_INS_OR: op->type = R_ANAL_OP_TYPE_OR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,|=", src, dst); free (src); free (dst); } break; case X86_INS_INC: op->type = R_ANAL_OP_TYPE_ADD; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,++=", src); free (src); } break; case X86_INS_DEC: op->type = R_ANAL_OP_TYPE_SUB; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,--=", src); free (src); } break; case X86_INS_SUB: case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "-"); esilprintf (op, "%s,%s,$c,cf,=,$z,zf,=,$s,sf,=,$o,of,=", src, dst); // TODO: update flags free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = INSOP(1).imm; } } break; case X86_INS_LIDT: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_SIDT: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_RDRAND: case X86_INS_RDSEED: case X86_INS_RDMSR: case X86_INS_RDPMC: case X86_INS_RDTSC: case X86_INS_RDTSCP: case X86_INS_CRC32: case X86_INS_SHA1MSG1: case X86_INS_SHA1MSG2: case X86_INS_SHA1NEXTE: case X86_INS_SHA1RNDS4: case X86_INS_SHA256MSG1: case X86_INS_SHA256MSG2: case X86_INS_SHA256RNDS2: case X86_INS_AESDECLAST: case X86_INS_AESDEC: case X86_INS_AESENCLAST: case X86_INS_AESENC: case X86_INS_AESIMC: case X86_INS_AESKEYGENASSIST: // AES instructions op->family = R_ANAL_OP_FAMILY_CRYPTO; op->type = R_ANAL_OP_TYPE_MOV; // XXX break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "&"); // TODO: update of = cf = 0 // TODO: update sf, zf and pf // TODO: af is undefined esilprintf (op, "0,of,=,0,cf,=," // set carry and overflow flags "%s,%s," // set reg value "$z,zf,=," // update zero flag "$s,sf,=," // update sign flag "$o,pf,=", // update parity flag // TODO: add sign and parity flags here src, dst); free (src); free (dst); } break; case X86_INS_DIV: case X86_INS_IDIV: op->type = R_ANAL_OP_TYPE_DIV; if (a->decode) { int width = INSOP(0).size; char *dst = getarg (&gop, 0, 0, NULL); const char *r_ax = (width==2)?"ax": (width==4)?"eax":"rax"; const char *r_dx = (width==2)?"dx": (width==4)?"edx":"rdx"; // TODO update flags & handle signedness esilprintf (op, "%s,%s,%%,%s,=,%s,%s,/,%s,=", dst, r_ax, r_dx, dst, r_ax, r_ax); free (dst); } break; case X86_INS_MUL: case X86_INS_MULX: case X86_INS_MULPD: case X86_INS_MULPS: case X86_INS_MULSD: case X86_INS_MULSS: op->type = R_ANAL_OP_TYPE_MUL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "*"); if (!src && dst) { switch (dst[0]) { case 'r': src = strdup ("rax"); break; case 'e': src = strdup ("eax"); break; default: src = strdup ("al"); break; } } esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } break; case X86_INS_PACKSSDW: case X86_INS_PACKSSWB: case X86_INS_PACKUSWB: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_PADDB: case X86_INS_PADDD: case X86_INS_PADDW: case X86_INS_PADDSB: case X86_INS_PADDSW: case X86_INS_PADDUSB: case X86_INS_PADDUSW: op->type = R_ANAL_OP_TYPE_ADD; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_FADD: case X86_INS_FADDP: op->family = R_ANAL_OP_FAMILY_FPU; /* pass thru */ case X86_INS_ADD: case X86_INS_ADDPS: case X86_INS_ADDSD: case X86_INS_ADDSS: case X86_INS_ADDSUBPD: case X86_INS_ADDSUBPS: case X86_INS_ADDPD: case X86_INS_XADD: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { if (INSOP(0).type == X86_OP_MEM) { char *src = getarg (&gop, 1, 0, NULL); char *src2 = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); // TODO: update flags esilprintf (op, "%s,%s,+,%s", src, src2, dst); free (src); free (src2); free (dst); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "+"); esilprintf (op, "%s,%s", src, dst); // TODO: update flags free (src); free (dst); } } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -INSOP(1).imm; } } break; /* Direction flag */ case X86_INS_CLD: if (a->decode) esilprintf (op, "0,df,="); break; case X86_INS_STD: if (a->decode) esilprintf (op, "1,df,="); break; } } //#if X86_GRP_PRIVILEGE>0 if (insn) { #if HAVE_CSGRP_PRIVILEGE if (cs_insn_group (handle, insn, X86_GRP_PRIVILEGE)) op->family = R_ANAL_OP_FAMILY_PRIV; #endif #if !USE_ITER_API cs_free (insn, n); #endif } cs_close (&handle); return op->size; }
int32_t gbox_cmd_hello(struct s_client *cli, uchar *data, int32_t n) { struct gbox_peer *peer = cli->gbox; int32_t i; int32_t ncards_in_msg = 0; int32_t payload_len = n; //TODO: checkcode_len can be made void int32_t checkcode_len = 0; int32_t hostname_len = 0; int32_t footer_len = 0; uint8_t *ptr = 0; if(!(data[0] == 0x48 && data[1] == 0x49)) // if not MSG_HELLO1 { gbox_decompress(data, &payload_len); } cs_ddump_mask(D_READER, data, payload_len, "gbox: decompressed data (%d bytes):", payload_len); if((data[0x0B] == 0) | ((data[0x0A] == 1) && (data[0x0B] == 0x80))) { if(peer->gbox.cards) { gbox_remove_cards_without_goodsids(peer->gbox.cards); } else { peer->gbox.cards = ll_create("peer.cards"); } } if((data[0xB] & 0xF) == 0) { checkcode_len = 7; hostname_len = data[payload_len - 1]; footer_len = hostname_len + 2; } if(data[0] == 0x48 && data[1] == 0x49) // if MSG_HELLO1 { ptr = data + 11; } else { ptr = data + 12; } while(ptr < data + payload_len - footer_len - checkcode_len - 1) { uint16_t caid; uint32_t provid; uint32_t provid1; switch(ptr[0]) { //Viaccess case 0x05: caid = ptr[0] << 8; provid = ptr[1] << 16 | ptr[2] << 8 | ptr[3]; break; //Cryptoworks case 0x0D: caid = ptr[0] << 8 | ptr[1]; provid = ptr[2]; break; default: caid = ptr[0] << 8 | ptr[1]; provid = ptr[2] << 8 | ptr[3]; break; } //caid check if(chk_ctab(caid, &cli->reader->ctab)) { provid1 = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; uint8_t ncards = ptr[4]; ptr += 5; for(i = 0; i < ncards; i++) { // for all n cards and current caid/provid, // create card info from data and add card to peer.cards struct gbox_card *card; if(!cs_malloc(&card, sizeof(struct gbox_card))) { continue; } card->caid = caid; card->provid = provid; card->provid_1 = provid1; card->slot = ptr[0]; card->dist = ptr[1] & 0xf; card->lvl = ptr[1] >> 4; card->peer_id = ptr[2] << 8 | ptr[3]; ptr += 4; if((cli->reader->gbox_maxdist >= card->dist) && (card->peer_id != local_gbox.id)) { LL_ITER it = ll_iter_create(peer->gbox.cards); struct gbox_card *card_s; uint8_t v_card = 0; while((card_s = ll_iter_next(&it))) // don't add card if already in peer.cards list { if(card_s->peer_id == card->peer_id && card_s->provid_1 == card->provid_1) { gbox_free_card(card); card = NULL; v_card = 1; break; } } if(v_card != 1) // new card - not in list { card->badsids = ll_create("badsids"); card->goodsids = ll_create("goodsids"); ll_append(peer->gbox.cards, card); ncards_in_msg++; cs_debug_mask(D_READER, " card: caid=%04x, provid=%06x, slot=%d, level=%d, dist=%d, peer=%04x", card->caid, card->provid, card->slot, card->lvl, card->dist, card->peer_id); } } else // don't add card { gbox_free_card(card); card = NULL; } cli->reader->tcp_connected = 2; // we have card } // end for ncards } else {
static int32_t ecm_ratelimit_findspace(struct s_reader *reader, ECM_REQUEST *er, struct ecmrl rl, int32_t reader_mode) { int32_t h, foundspace = -1; int32_t maxecms = MAXECMRATELIMIT; // init maxecms int32_t totalecms = 0; // init totalecms struct timeb actualtime; cs_ftime(&actualtime); for(h = 0; h < MAXECMRATELIMIT; h++) // release slots with srvid that are overtime, even if not called from reader module to maximize available slots! { if(reader->rlecmh[h].last.time == -1) { continue; } int64_t gone = comp_timeb(&actualtime, &reader->rlecmh[h].last); if( gone >= (reader->rlecmh[h].ratelimittime + reader->rlecmh[h].srvidholdtime) || gone < 0) // gone <0 fixup for bad systemtime on dvb receivers while changing transponders { cs_log_dbg(D_CLIENT, "ratelimiter srvid %04X released from slot %d/%d of reader %s (%"PRId64">=%d ratelimit ms + %d ms srvidhold!)", reader->rlecmh[h].srvid, h + 1, MAXECMRATELIMIT, reader->label, gone, reader->rlecmh[h].ratelimittime, reader->rlecmh[h].srvidholdtime); reader->rlecmh[h].last.time = -1; reader->rlecmh[h].srvid = -1; reader->rlecmh[h].kindecm = 0; reader->rlecmh[h].once = 0; } if(reader->rlecmh[h].last.time == -1) { continue; } if(reader->rlecmh[h].ratelimitecm < maxecms) { maxecms = reader->rlecmh[h].ratelimitecm; } // we found a more critical ratelimit srvid totalecms++; } cs_log_dbg(D_CLIENT, "ratelimiter found total of %d srvid for reader %s most critical is limited to %d requests", totalecms, reader->label, maxecms); if(reader->cooldown[0] && reader->cooldownstate != 1) { maxecms = MAXECMRATELIMIT; } // dont apply ratelimits if cooldown isnt in use or not in effect for(h = 0; h < MAXECMRATELIMIT; h++) // check if srvid is already in a slot { if(reader->rlecmh[h].last.time == -1) { continue; } if(reader->rlecmh[h].srvid == er->srvid && reader->rlecmh[h].caid == rl.caid && reader->rlecmh[h].provid == rl.provid && (!reader->rlecmh[h].chid || (reader->rlecmh[h].chid == rl.chid))) { int64_t gone = comp_timeb(&actualtime, &reader->rlecmh[h].last); cs_log_dbg(D_CLIENT, "ratelimiter found srvid %04X for %"PRId64" ms in slot %d/%d of reader %s", er->srvid, gone, h + 1, MAXECMRATELIMIT, reader->label); // check ecmunique if enabled and ecmunique time is done if(reader_mode && reader->ecmunique) { gone = comp_timeb(&actualtime, &reader->rlecmh[h].last); if(gone < reader->ratelimittime) { if(memcmp(reader->rlecmh[h].ecmd5, er->ecmd5, CS_ECMSTORESIZE)) //some boxes seem to send different ecms but asking in fact for same cw! { // different ecm request than one in the slot! if(er->ecm[0] == reader->rlecmh[h].kindecm) { // same ecm type! char ecmd5[17 * 3]; cs_hexdump(0, reader->rlecmh[h].ecmd5, 16, ecmd5, sizeof(ecmd5)); cs_log_dbg(D_CLIENT, "ratelimiter ecm %s in this slot for next %d ms!", ecmd5, (int)(reader->rlecmh[h].ratelimittime - gone)); struct ecm_request_t *erold = NULL; if(!cs_malloc(&erold, sizeof(struct ecm_request_t))) { return -2; } memcpy(erold, er, sizeof(struct ecm_request_t)); // copy ecm all memcpy(erold->ecmd5, reader->rlecmh[h].ecmd5, CS_ECMSTORESIZE); // replace md5 hash struct ecm_request_t *ecm = NULL; ecm = check_cache(erold, erold->client); //CHECK IF FOUND ECM IN CACHE NULLFREE(erold); if(ecm) //found in cache { write_ecm_answer(reader, er, ecm->rc, ecm->rcEx, ecm->cw, NULL, 0, &ecm->cw_ex); } // return controlword of the ecm sitting in the slot! else { write_ecm_answer(reader, er, E_NOTFOUND, E2_RATELIMIT, NULL, "Ratelimiter: no slots free!", 0, NULL); } NULLFREE(ecm); return -2; } } } if((er->ecm[0] != reader->rlecmh[h].kindecm) && (gone <= reader->ratelimittime)) { if(!reader->rlecmh[h].once) // 1 premature ecmtype change is allowed (useful right after zapping to a channel!) { reader->rlecmh[h].once = 1; cs_log_dbg(D_CLIENT, "ratelimiter changing slot %d srvid %04X ecmtype once from %s to %s!", h+1, er->srvid, (reader->rlecmh[h].kindecm == 0x80 ? "even":"odd"), (er->ecm[0] == 0x80 ? "even":"odd")); } else { cs_log_dbg(D_CLIENT, "ratelimiter srvid %04X only allowing ecmtype %s for next %d ms in slot %d/%d of reader %s -> skipping this slot!", reader->rlecmh[h].srvid, (reader->rlecmh[h].kindecm == 0x80 ? "even" : "odd"), (int)(reader->rlecmh[h].ratelimittime - gone), h + 1, maxecms, reader->label); continue; } } } if(h > 0) { for(foundspace = 0; foundspace < h; foundspace++) // check for free lower slot { if(reader->rlecmh[foundspace].last.time == -1) { reader->rlecmh[foundspace] = reader->rlecmh[h]; // replace ecm request info reader->rlecmh[h].last.time = -1; reader->rlecmh[h].srvid = -1; reader->rlecmh[h].kindecm = 0; reader->rlecmh[h].once = 0; if(foundspace < maxecms) { cs_log_dbg(D_CLIENT, "ratelimiter moved srvid %04X to slot %d/%d of reader %s", er->srvid, foundspace + 1, maxecms, reader->label); return foundspace; // moving to lower free slot! } else { cs_log_dbg(D_CLIENT, "ratelimiter removed srvid %04X from slot %d/%d of reader %s", er->srvid, foundspace + 1, maxecms, reader->label); reader->rlecmh[foundspace].last.time = -1; // free this slot since we are over ratelimit! return -1; // sorry, ratelimit! } } } } if(h < maxecms) // found but cant move to lower position! { return h; // return position if within ratelimits! } else { reader->rlecmh[h].last.time = -1; // free this slot since we are over ratelimit! reader->rlecmh[h].srvid = -1; reader->rlecmh[h].kindecm = 0; reader->rlecmh[h].once = 0; cs_log_dbg(D_CLIENT, "ratelimiter removed srvid %04X from slot %d/%d of reader %s", er->srvid, h + 1, maxecms, reader->label); return -1; // sorry, ratelimit! } } } // srvid not found in slots! // do we use cooldown at all, are we in cooldown fase? if((reader->cooldown[0] && reader->cooldownstate == 1) || !reader->cooldown[0]) { // we are in cooldown or no cooldown configured! if(totalecms + 1 > maxecms || totalecms + 1 > rl.ratelimitecm) // check if this channel fits in! { cs_log_dbg(D_CLIENT, "ratelimiter for reader %s has no free slots!", reader->label); return -1; } } else { maxecms = MAXECMRATELIMIT; // no limits right now! } for(h = 0; h < maxecms; h++) // check for free slot { if(reader->rlecmh[h].last.time == -1) { if(reader_mode) { cs_log_dbg(D_CLIENT, "ratelimiter added srvid %04X to slot %d/%d of reader %s", er->srvid, h + 1, maxecms, reader->label); } return h; // free slot found -> assign it! } else { int64_t gone = comp_timeb(&actualtime, &reader->rlecmh[h].last); cs_log_dbg(D_CLIENT, "ratelimiter srvid %04X for %"PRId64" ms present in slot %d/%d of reader %s", reader->rlecmh[h].srvid, gone , h + 1, maxecms, reader->label); } //occupied slots } foundspace = dvbapi_override_prio(reader, er, maxecms, &actualtime); if (foundspace > -1) return foundspace; return (-1); // no slot found }
static void write_to_log_int(char *txt, uint8_t header_len, uint8_t hdr_logcount_offset, uint8_t hdr_date_offset, uint8_t hdr_time_offset, uint8_t hdr_info_offset) { #if !defined(WEBIF) && !defined(MODULE_MONITOR) if(cfg.disablelog) { return; } #endif char *newtxt = cs_strdup(txt); if(!newtxt) { return; } struct s_log *log; if(!cs_malloc(&log, sizeof(struct s_log))) { NULLFREE(newtxt); return; } log->txt = newtxt; log->header_len = header_len; log->header_logcount_offset = hdr_logcount_offset; log->header_date_offset = hdr_date_offset; log->header_time_offset = hdr_time_offset; log->header_info_offset = hdr_info_offset; log->direct_log = 0; struct s_client *cl = cur_client(); log->cl_usr = ""; if(!cl) { log->cl_text = "undef"; log->cl_typ = ' '; } else { switch(cl->typ) { case 'c': case 'm': if(cl->account) { log->cl_text = cl->account->usr; log->cl_usr = cl->account->usr; } else { log->cl_text = ""; } break; case 'p': case 'r': log->cl_text = cl->reader ? cl->reader->label : ""; break; default: log->cl_text = "server"; break; } log->cl_typ = cl->typ; } if(exit_oscam == 1 || cfg.disablelog) //Exit or log disabled. if disabled, just display on webif/monitor { char buf[LOG_BUF_SIZE]; cs_strncpy(buf, log->txt, LOG_BUF_SIZE); write_to_log(buf, log, 1); NULLFREE(log->txt); NULLFREE(log); } else { log_list_add(log); } }
csEventFlattenerError csEventFlattener::Unflatten (iObjectRegistry *object_reg, iEvent* event, const char *buffer, size_t length) { csMemFile b((char *)buffer, length, csMemFile::DISPOSITION_IGNORE); uint8 ui8; int8 i8; uint16 ui16; int16 i16; uint32 ui32; int32 i32; uint64 ui64; int64 i64; double d; char *name; size_t size; b.Read((char *)&ui32, sizeof(ui32)); // protocol version ui32 = csLittleEndian::Convert (ui32); if (ui32 != CS_CRYSTAL_PROTOCOL) { //csPrintf("protocol version invalid: %" PRIX32 "\n", ui32); return csEventFlattenerErrorWrongFormat; } b.Read((char *)&ui64, sizeof(uint64)); // packet size size = csLittleEndian::Convert (ui64); b.Read((char *)&ui32, sizeof(uint32)); // iEvent.Time event->Time = csLittleEndian::Convert (ui32); b.Read((char *)&event->Broadcast, sizeof(uint8)); // iEvent.Broadcast flag b.Read((char *)&ui16, sizeof(uint16)); // textual name length ui16 = csLittleEndian::Convert (ui16); char *buf = (char *) cs_malloc(ui16+1); b.Read(buf, ui16); // textual name buf[ui16] = '\0'; event->Name = csEventNameRegistry::GetID(object_reg, buf); // EventID cs_free(buf); while (b.GetPos() < size) { b.Read((char *)&ui16, sizeof(uint16)); ui16 = csLittleEndian::Convert (ui16); name = new char[ui16+1]; b.Read(name, ui16); name[ui16] = 0; b.Read((char *)&ui8, sizeof(uint8)); switch(ui8) { case CS_DATATYPE_INT8: b.Read((char *)&i8, sizeof(int8)); event->Add (name, i8); break; case CS_DATATYPE_UINT8: b.Read((char *)&ui8, sizeof(uint8)); event->Add (name, ui8); break; case CS_DATATYPE_INT16: b.Read((char *)&i16, sizeof(int16)); i16 = csLittleEndian::Convert (i16); event->Add (name, i16); break; case CS_DATATYPE_UINT16: b.Read((char *)&ui16, sizeof(uint16)); ui16 = csLittleEndian::Convert (ui16); event->Add (name, ui16); break; case CS_DATATYPE_INT32: b.Read((char *)&i32, sizeof(int32)); i32 = csLittleEndian::Convert (i32); event->Add (name, i32); break; case CS_DATATYPE_UINT32: b.Read((char *)&ui32, sizeof(uint32)); ui32 = csLittleEndian::Convert (ui32); event->Add (name, ui32); break; case CS_DATATYPE_INT64: b.Read((char *)&i64, sizeof(int64)); i64 = csLittleEndian::Convert (i64); event->Add (name, i64); break; case CS_DATATYPE_UINT64: b.Read((char *)&ui64, sizeof(uint64)); ui64 = csLittleEndian::Convert (ui64); event->Add (name, ui64); break; case CS_DATATYPE_DOUBLE: b.Read((char *)&i64, sizeof(int64)); d = csLongLongToDouble(i64); event->Add (name, d); break; case CS_DATATYPE_DATABUFFER: { b.Read((char *)&ui64, sizeof(uint64)); ui64 = csLittleEndian::Convert (ui64); char* data = new char[ui64]; b.Read(data, ui64); event->Add (name, data, ui64); delete[] data; } break; case CS_DATATYPE_EVENT: { b.Read((char *)&ui64, sizeof (uint64)); ui64 = csLittleEndian::Convert (ui64); csRef<iEvent> e; e.AttachNew (new csEvent ()); event->Add (name, e); csEventFlattenerError unflattenResult = Unflatten (object_reg, e, buffer+b.GetPos(), ui64); if (unflattenResult != csEventFlattenerErrorNone) { delete[] name; return unflattenResult; } b.SetPos (b.GetPos() + (size_t)ui64); } break; default: break; } delete[] name; } return csEventFlattenerErrorNone; }
void add_cache(ECM_REQUEST *er){ if(!er->csp_hash) return; ECMHASH *result = NULL; CW *cw = NULL; #ifdef CS_CACHEEX bool add_new_cw=false; #endif pthread_rwlock_wrlock(&cache_lock); //add csp_hash to cache result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t), &compare_csp_hash); if(!result){ if(cs_malloc(&result, sizeof(ECMHASH))){ result->csp_hash = er->csp_hash; init_hash_table(&result->ht_cw, &result->ll_cw); cs_ftime(&result->first_recv_time); add_hash_table(&ht_cache, &result->ht_node, &ll_cache, &result->ll_node, result, &result->csp_hash, sizeof(int32_t)); }else{ pthread_rwlock_unlock(&cache_lock); cs_log("ERROR: NO added HASH to cache!!"); return; } } cs_ftime(&result->upd_time); //need to be updated at each cw! We use it for deleting this hash when no more cws arrive inside max_cache_time! //add cw to this csp hash cw = find_hash_table(&result->ht_cw, er->cw, sizeof(er->cw), &compare_cw); if(!cw){ if(count_hash_table(&result->ht_cw)>=10){ //max 10 different cws stored pthread_rwlock_unlock(&cache_lock); return; } while(1){ if(cs_malloc(&cw, sizeof(CW))){ memcpy(cw->cw, er->cw, sizeof(er->cw)); cw->odd_even = get_odd_even(er); cw->cwc_cycletime = er->cwc_cycletime; cw->cwc_next_cw_cycle = er->cwc_next_cw_cycle; cw->count= 0; cw->csp = 0; cw->cacheex = 0; cw->localcards=0; cw->proxy=0; cw->grp = 0; cw->caid = er->caid; cw->prid = er->prid; cw->srvid = er->srvid; cw->selected_reader=er->selected_reader; #ifdef CS_CACHEEX cw->cacheex_src=er->cacheex_src; #endif cw->pushout_client = NULL; while(1){ if (pthread_rwlock_init(&cw->pushout_client_lock, NULL) == 0) break; cs_log("Error creating lock pushout_client_lock!"); cs_sleepms(1); } add_hash_table(&result->ht_cw, &cw->ht_node, &result->ll_cw, &cw->ll_node, cw, cw->cw, sizeof(er->cw)); #ifdef CS_CACHEEX add_new_cw=true; #endif break; } cs_log("ERROR: NO added CW to cache!! Re-trying..."); cs_sleepms(1); } } //update if answered from csp/cacheex/local_proxy if(er->from_cacheex) cw->cacheex = 1; if(er->from_csp) cw->csp = 1; #ifdef CS_CACHEEX if(!er->cacheex_src){ #endif if(is_localreader(er->selected_reader, er)) cw->localcards=1; else cw->proxy = 1; #ifdef CS_CACHEEX } #endif //always update group and counter cw->grp |= er->grp; cw->count++; //sort cw_list by counter (DESC order) if(cw->count>1) sort_list(&result->ll_cw, count_sort); pthread_rwlock_unlock(&cache_lock); #ifdef CS_CACHEEX er->cw_cache=cw; cacheex_cache_push(er); //cacheex debug log lines and cw diff stuff if(check_client(er->cacheex_src)){ if(add_new_cw){ debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src)); CW *cw_first = get_first_cw(result, er); if(er && cw_first){ //compare er cw with mostly counted cached cw if(memcmp(er->cw, cw_first->cw, sizeof(er->cw)) != 0) { er->cacheex_src->cwcacheexerrcw++; if (er->cacheex_src->account) er->cacheex_src->account->cwcacheexerrcw++; if (((0x0200| 0x0800) & cs_dblevel)) { //avoid useless operations if debug is not enabled char cw1[16*3+2], cw2[16*3+2]; cs_hexdump(0, er->cw, 16, cw1, sizeof(cw1)); cs_hexdump(0, cw_first->cw, 16, cw2, sizeof(cw2)); char ip1[20]="", ip2[20]=""; if (check_client(er->cacheex_src)) cs_strncpy(ip1, cs_inet_ntoa(er->cacheex_src->ip), sizeof(ip1)); if (check_client(cw_first->cacheex_src)) cs_strncpy(ip2, cs_inet_ntoa(cw_first->cacheex_src->ip), sizeof(ip2)); else if (cw_first->selected_reader && check_client(cw_first->selected_reader->client)) cs_strncpy(ip2, cs_inet_ntoa(cw_first->selected_reader->client->ip), sizeof(ip2)); debug_ecm(D_CACHEEX| D_CSP, "WARNING: Different CWs %s from %s(%s)<>%s(%s): %s<>%s ", buf, er->from_csp ? "csp" : username(er->cacheex_src), ip1, check_client(cw_first->cacheex_src)?username(cw_first->cacheex_src):(cw_first->selected_reader?cw_first->selected_reader->label:"unknown/csp"), ip2, cw1, cw2); } } } }else debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src)); } #endif }
static int32_t dre_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count) { if(*emm_filters == NULL) { const unsigned int max_filter_count = 7; if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter))) { return ERROR; } struct s_csystem_emm_filter *filters = *emm_filters; *filter_count = 0; int32_t idx = 0; filters[idx].type = EMM_SHARED; filters[idx].enabled = 1; filters[idx].filter[0] = 0x80; filters[idx].filter[1] = rdr->sa[0][0]; filters[idx].mask[0] = 0xF2; filters[idx].mask[1] = 0xFF; idx++; filters[idx].type = EMM_SHARED; filters[idx].enabled = 1; filters[idx].filter[0] = 0x82; filters[idx].filter[1] = rdr->sa[0][0]; filters[idx].mask[0] = 0xF3; filters[idx].mask[1] = 0xFF; idx++; filters[idx].type = EMM_SHARED; filters[idx].enabled = 1; filters[idx].filter[0] = 0x83; filters[idx].filter[1] = rdr->sa[0][0]; filters[idx].mask[0] = 0xF3; if(rdr->caid == 0x4ae1) { memcpy(&filters[idx].filter[1], &rdr->sa[0][0], 4); memset(&filters[idx].mask[1], 0xFF, 4); } filters[idx].mask[1] = 0xFF; idx++; filters[idx].type = EMM_SHARED; filters[idx].enabled = 1; filters[idx].filter[0] = 0x86; filters[idx].filter[1] = rdr->sa[0][0]; filters[idx].mask[0] = 0xFF; filters[idx].mask[1] = 0xFF; idx++; filters[idx].type = EMM_SHARED; filters[idx].enabled = 1; filters[idx].filter[0] = 0x8c; filters[idx].filter[1] = rdr->sa[0][0]; filters[idx].mask[0] = 0xFF; filters[idx].mask[1] = 0xFF; idx++; filters[idx].type = EMM_SHARED; filters[idx].enabled = 1; filters[idx].filter[0] = 0x89; filters[idx].mask[0] = 0xFF; // FIXME: Seems to be that SA is only used with caid 0x4ae1 if(rdr->caid == 0x4ae1) { memcpy(&filters[idx].filter[1], &rdr->sa[0][0], 4); memset(&filters[idx].mask[1], 0xFF, 4); } idx++; filters[idx].type = EMM_UNIQUE; filters[idx].enabled = 1; filters[idx].filter[0] = 0x87; filters[idx].mask[0] = 0xFF; //FIXME: No filter for hexserial idx++; *filter_count = idx; } return OK; }
/* sparse QR factorization [V,beta,pinv,R] = qr (A) */ csn *cs_qr (const cs *A, const css *S) { double *Rx, *Vx, *Ax, *x, *Beta ; int i, k, p, n, vnz, p1, top, m2, len, col, rnz, *s, *leftmost, *Ap, *Ai, *parent, *Rp, *Ri, *Vp, *Vi, *w, *pinv, *q ; cs *R, *V ; csn *N ; if (!CS_CSC (A) || !S) return (NULL) ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; q = S->q ; parent = S->parent ; pinv = S->pinv ; m2 = S->m2 ; vnz = (int)S->lnz ; rnz = (int)S->unz ; leftmost = S->leftmost ; w = (int*) cs_malloc (m2+n, sizeof (int)) ; /* get int workspace */ x = (double*) cs_malloc (m2, sizeof (double)) ; /* get double workspace */ N = (csn*) cs_calloc (1, sizeof (csn)) ; /* allocate result */ if (!w || !x || !N) return (cs_ndone (N, NULL, w, x, 0)) ; s = w + m2 ; /* s is size n */ for (k = 0 ; k < m2 ; k++) x [k] = 0 ; /* clear workspace x */ N->L = V = cs_spalloc (m2, n, vnz, 1, 0) ; /* allocate result V */ N->U = R = cs_spalloc (m2, n, rnz, 1, 0) ; /* allocate result R */ N->B = Beta = (double*) cs_malloc (n, sizeof (double)) ; /* allocate result Beta */ if (!R || !V || !Beta) return (cs_ndone (N, NULL, w, x, 0)) ; Rp = R->p ; Ri = R->i ; Rx = R->x ; Vp = V->p ; Vi = V->i ; Vx = V->x ; for (i = 0 ; i < m2 ; i++) w [i] = -1 ; /* clear w, to mark nodes */ rnz = 0 ; vnz = 0 ; for (k = 0 ; k < n ; k++) /* compute V and R */ { Rp [k] = rnz ; /* R(:,k) starts here */ Vp [k] = p1 = vnz ; /* V(:,k) starts here */ w [k] = k ; /* add V(k,k) to pattern of V */ Vi [vnz++] = k ; top = n ; col = q ? q [k] : k ; for (p = Ap [col] ; p < Ap [col+1] ; p++) /* find R(:,k) pattern */ { i = leftmost [Ai [p]] ; /* i = min(find(A(i,q))) */ for (len = 0 ; w [i] != k ; i = parent [i]) /* traverse up to k */ { s [len++] = i ; w [i] = k ; } while (len > 0) s [--top] = s [--len] ; /* push path on stack */ i = pinv [Ai [p]] ; /* i = permuted row of A(:,col) */ x [i] = Ax [p] ; /* x (i) = A(:,col) */ if (i > k && w [i] < k) /* pattern of V(:,k) = x (k+1:m) */ { Vi [vnz++] = i ; /* add i to pattern of V(:,k) */ w [i] = k ; } } for (p = top ; p < n ; p++) /* for each i in pattern of R(:,k) */ { i = s [p] ; /* R(i,k) is nonzero */ cs_happly (V, i, Beta [i], x) ; /* apply (V(i),Beta(i)) to x */ Ri [rnz] = i ; /* R(i,k) = x(i) */ Rx [rnz++] = x [i] ; x [i] = 0 ; if (parent [i] == k) vnz = cs_scatter (V, i, 0, w, NULL, k, V, vnz); } for (p = p1 ; p < vnz ; p++) /* gather V(:,k) = x */ { Vx [p] = x [Vi [p]] ; x [Vi [p]] = 0 ; } Ri [rnz] = k ; /* R(k,k) = norm (x) */ Rx [rnz++] = cs_house (Vx+p1, Beta+k, vnz-p1) ; /* [v,beta]=house(x) */ } Rp [n] = rnz ; /* finalize R */ Vp [n] = vnz ; /* finalize V */ return (cs_ndone (N, NULL, w, x, 1)) ; /* success */ }
/* * Creates a string ready to write as a token into config or WebIf for AESKeys. You must free the returned value through free_mk_t(). */ char *mk_t_aeskeys(struct s_reader *rdr) { AES_ENTRY *current = rdr->aes_list; int32_t i, pos = 0, needed = 1, prevKeyid = 0, prevCaid = 0; uint32_t prevIdent = 0; /* Precheck for the approximate size that we will need; it's a bit overestimated but we correct that at the end of the function */ while(current) { /* The caid, ident, "@" and the trailing ";" need to be output when they are changing */ if(prevCaid != current->caid || prevIdent != current->ident) needed += 12 + (current->keyid * 2); /* "0" keys are not saved so we need to check for gaps */ else if(prevKeyid != current->keyid + 1) needed += (current->keyid - prevKeyid - 1) * 2; /* The 32 byte key plus either the (heading) ":" or "," */ needed += 33; prevCaid = current->caid; prevIdent = current->ident; prevKeyid = current->keyid; current = current->next; } /* Set everything back and now create the string */ current = rdr->aes_list; prevCaid = 0; prevIdent = 0; prevKeyid = 0; char tmp[needed]; char dot; if(needed == 1) tmp[0] = '\0'; char tmpkey[33]; while(current) { /* A change in the ident or caid means that we need to output caid and ident */ if(prevCaid != current->caid || prevIdent != current->ident) { if(pos > 0) { tmp[pos] = ';'; ++pos; } pos += snprintf(tmp+pos, sizeof(tmp)-pos, "%04X@%06X", current->caid, current->ident); prevKeyid = -1; dot = ':'; } else dot = ','; /* "0" keys are not saved so we need to check for gaps and output them! */ for (i = prevKeyid + 1; i < current->keyid; ++i) { pos += snprintf(tmp+pos, sizeof(tmp)-pos, "%c0", dot); dot = ','; } tmp[pos] = dot; ++pos; for (i = 0; i < 16; ++i) snprintf(tmpkey + (i*2), sizeof(tmpkey) - (i*2), "%02X", current->plainkey[i]); /* A key consisting of only FFs has a special meaning (just return what the card outputted) and can be specified more compact */ if(strcmp(tmpkey, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") == 0) pos += snprintf(tmp+pos, sizeof(tmp)-pos, "FF"); else pos += snprintf(tmp+pos, sizeof(tmp)-pos, "%s", tmpkey); prevCaid = current->caid; prevIdent = current->ident; prevKeyid = current->keyid; current = current->next; } /* copy to result array of correct size */ char *value; if (pos == 0 || !cs_malloc(&value, pos + 1)) return ""; memcpy(value, tmp, pos + 1); return(value); }
void* Malloc (size_t size) { return cs_malloc (size); }
int32_t stapi_open(void) { uint32_t ErrorCode; DIR *dirp; struct dirent entry, *dp = NULL; struct stat buf; int32_t i; char pfad[80]; stapi_on=1; int32_t stapi_priority=0; dirp = opendir(PROCDIR); if (!dirp) { cs_log("opendir failed (errno=%d %s)", errno, strerror(errno)); return 0; } memset(dev_list, 0, sizeof(struct STDEVICE)*PTINUM); if (dvbapi_priority) { struct s_dvbapi_priority *p; for (p=dvbapi_priority; p != NULL; p=p->next) { if (p->type=='s') { stapi_priority=1; break; } } } if (!stapi_priority) { cs_log("WARNING: no PTI devices defined, stapi disabled"); return 0; } oscam_stapi_CheckVersion(); i=0; while (!cs_readdir_r(dirp, &entry, &dp)) { if (!dp) break; snprintf(pfad, sizeof(pfad), "%s%s", PROCDIR, dp->d_name); if (stat(pfad,&buf) != 0) continue; if (!(buf.st_mode & S_IFDIR && strncmp(dp->d_name, ".", 1)!=0)) continue; int32_t do_open=0; struct s_dvbapi_priority *p; for (p=dvbapi_priority; p != NULL; p=p->next) { if (p->type!='s') continue; if(strcmp(dp->d_name, p->devname)==0) { do_open=1; break; } } if (!do_open) { cs_log("PTI: %s skipped", dp->d_name); continue; } ErrorCode= oscam_stapi_Open(dp->d_name, &dev_list[i].SessionHandle); if (ErrorCode != 0) { cs_log("STPTI_Open ErrorCode: %d", ErrorCode); continue; } //debug //oscam_stapi_Capability(dp->d_name); cs_strncpy(dev_list[i].name,dp->d_name, sizeof(dev_list[i].name)); cs_log("PTI: %s open %d", dp->d_name, i); ErrorCode = oscam_stapi_SignalAllocate(dev_list[i].SessionHandle, &dev_list[i].SignalHandle); if (ErrorCode != 0) cs_log("SignalAllocate: ErrorCode: %d SignalHandle: %x", ErrorCode, dev_list[i].SignalHandle); i++; if (i>=PTINUM) break; } closedir(dirp); if (i==0) return 0; pthread_mutex_init(&filter_lock, NULL); for (i=0;i<PTINUM;i++) { if (dev_list[i].SessionHandle==0) continue; struct read_thread_param *para; if (!cs_malloc(¶, sizeof(struct read_thread_param))) return 0; para->id=i; para->cli=cur_client(); int32_t ret = pthread_create(&dev_list[i].thread, NULL, stapi_read_thread, (void *)para); if(ret){ cs_log("ERROR: can't create stapi read thread (errno=%d %s)", ret, strerror(ret)); return 0; } else pthread_detach(dev_list[i].thread); } atexit(stapi_off); cs_log("liboscam_stapi v.%s initialized", oscam_stapi_LibVersion()); return 1; }
static int32_t cc_cacheex_push_out(struct s_client *cl, struct ecm_request_t *er) { int8_t rc = (er->rc < E_NOTFOUND) ? E_FOUND : er->rc; if(rc != E_FOUND && rc != E_UNHANDLED) { return -1; } //Maybe later we could support other rcs if(cl->reader) { if(!cl->reader->tcp_connected) { cc_cli_connect(cl); } } struct cc_data *cc = cl->cc; if(!cc || !cl->udp_fd) { cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl)); return (-1); } uint32_t size = sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw) + sizeof(uint8_t) + (ll_count(er->csp_lastnodes) + 1) * 8; unsigned char *buf; if(!cs_malloc(&buf, size + 20)) //camd35_send() adds +20 { return -1; } // build ecm message //buf[0] = er->caid >> 8; //buf[1] = er->caid & 0xff; //buf[2] = er->prid >> 24; //buf[3] = er->prid >> 16; //buf[4] = er->prid >> 8; //buf[5] = er->prid & 0xff; //buf[10] = er->srvid >> 8; //buf[11] = er->srvid & 0xff; buf[12] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) & 0xff; buf[13] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) >> 8; //buf[12] = 0; //buf[13] = 0; buf[14] = rc; i2b_buf(2, er->caid, buf + 0); i2b_buf(4, er->prid, buf + 2); i2b_buf(2, er->srvid, buf + 10); if(er->cwc_cycletime && er->cwc_next_cw_cycle < 2) { buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime if(er->cwc_next_cw_cycle == 1) { buf[18] = (buf[18] | 0x80); } // set bit 8 to high if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode) { cl->account->cwc_info++; } else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode)) { cl->cwc_info++; } cs_log_dbg(D_CWC, "CWC (CE) push to %s cycletime: %isek - nextcwcycle: CW%i for %04X:%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid); } buf[19] = er->ecm[0] != 0x80 && er->ecm[0] != 0x81 ? 0 : er->ecm[0]; uint8_t *ofs = buf + 20; //write oscam ecmd5: memcpy(ofs, er->ecmd5, sizeof(er->ecmd5)); //16 ofs += sizeof(er->ecmd5); //write csp hashcode: i2b_buf(4, htonl(er->csp_hash), ofs); ofs += 4; //write cw: memcpy(ofs, er->cw, sizeof(er->cw)); //16 ofs += sizeof(er->cw); //write node count: *ofs = ll_count(er->csp_lastnodes) + 1; ofs++; //write own node: memcpy(ofs, cc->node_id, 8); ofs += 8; //write other nodes: LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0); uint8_t *node; while((node = ll_li_next(li))) { memcpy(ofs, node, 8); ofs += 8; } ll_li_destroy(li); int32_t res = cc_cmd_send(cl, buf, size + 20, MSG_CACHE_PUSH); if(res > 0) // cache-ex is pushing out, so no receive but last_g should be updated otherwise disconnect! { if(cl->reader) { cl->reader->last_s = cl->reader->last_g = time((time_t *)0); } // correct if(cl) { cl->last = time(NULL); } } NULLFREE(buf); return res; }
static void do_emm_from_file(struct s_reader * reader) { //now here check whether we have EMM's on file to load and write to card: if (reader->emmfile == NULL) return; //handling emmfile char token[256]; FILE *fp; if (reader->emmfile[0] == '/') snprintf (token, sizeof(token), "%s", reader->emmfile); //pathname included else snprintf (token, sizeof(token), "%s%s", cs_confdir, reader->emmfile); //only file specified, look in confdir for this file if (!(fp = fopen (token, "rb"))) { rdr_log(reader, "ERROR: Cannot open EMM file '%s' (errno=%d %s)\n", token, errno, strerror(errno)); return; } EMM_PACKET *eptmp; if(!cs_malloc(&eptmp,sizeof(EMM_PACKET), -1)) { fclose (fp); return; } size_t ret = fread(eptmp, sizeof(EMM_PACKET), 1, fp); if (ret < 1 && ferror(fp)) { rdr_log(reader, "ERROR: Can't read EMM from file '%s' (errno=%d %s)", token, errno, strerror(errno)); free(eptmp); fclose(fp); return; } fclose (fp); eptmp->caid[0] = (reader->caid >> 8) & 0xFF; eptmp->caid[1] = reader->caid & 0xFF; if (reader->nprov > 0) memcpy(eptmp->provid, reader->prid[0], sizeof(eptmp->provid)); eptmp->l = eptmp->emm[2] + 3; struct s_cardsystem *cs = get_cardsystem_by_caid(reader->caid); if (cs && cs->get_emm_type && !cs->get_emm_type(eptmp, reader)) { rdr_debug_mask(reader, D_EMM, "emm skipped, get_emm_type() returns error"); free(eptmp); return; } //save old b_nano value //clear lsb and lsb+1, so no blocking, and no saving for this nano uint16_t save_s_nano = reader->s_nano; uint16_t save_b_nano = reader->b_nano; uint32_t save_saveemm = reader->saveemm; reader->s_nano = reader->b_nano = 0; reader->saveemm = 0; int32_t rc = reader_emm(reader, eptmp); if (rc == OK) rdr_log(reader, "EMM from file %s was successful written.", token); else rdr_log(reader, "ERROR: EMM read from file %s NOT processed correctly! (rc=%d)", token, rc); //restore old block/save settings reader->s_nano = save_s_nano; reader->b_nano = save_b_nano; reader->saveemm = save_saveemm; free(eptmp); }
int32_t init_sidtab(void) { FILE *fp = open_config_file(cs_sidt); if(!fp) { return 1; } int32_t nr, nro, nrr; char *value, *token; if(!cs_malloc(&token, MAXLINESIZE)) { return 1; } struct s_sidtab *ptr; struct s_sidtab *sidtab = (struct s_sidtab *)0; for(nro = 0, ptr = cfg.sidtab; ptr; nro++) { struct s_sidtab *ptr_next; ptr_next = ptr->next; free_sidtab(ptr); ptr = ptr_next; } nr = 0; nrr = 0; while(fgets(token, MAXLINESIZE, fp)) { int32_t l; if((l = strlen(trim(token))) < 3) { continue; } if((token[0] == '[') && (token[l - 1] == ']')) { token[l - 1] = 0; if(nr > MAX_SIDBITS) { fprintf(stderr, "Warning: Service No.%d - '%s' ignored. Max allowed Services %d\n", nr, strtolower(token + 1), MAX_SIDBITS); nr++; nrr++; } else { if(!cs_malloc(&ptr, sizeof(struct s_sidtab))) { NULLFREE(token); return (1); } if(sidtab) { sidtab->next = ptr; } else { cfg.sidtab = ptr; } sidtab = ptr; nr++; cs_strncpy(sidtab->label, strtolower(token + 1), sizeof(sidtab->label)); continue; } } if(!sidtab) { continue; } if(!(value = strchr(token, '='))) { continue; } *value++ = '\0'; chk_sidtab(trim(strtolower(token)), trim(strtolower(value)), sidtab); } NULLFREE(token); fclose(fp); #ifdef DEBUG_SIDTAB show_sidtab(cfg.sidtab); #endif ++cfg_sidtab_generation; cs_log("services reloaded: %d services freed, %d services loaded, rejected %d", nro, nr, nrr); return (0); }
static int32_t pcsc_init(struct s_reader *pcsc_reader) { ULONG rv; DWORD dwReaders = 0; LPSTR mszReaders = NULL; char *ptr, **readers = NULL; char *device = pcsc_reader->device; int32_t nbReaders; int32_t reader_nb; rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC establish context for PCSC pcsc_reader %s", device); SCARDCONTEXT hContext; memset(&hContext, 0, sizeof(hContext)); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if(rv == SCARD_S_SUCCESS) { if(!cs_malloc(&pcsc_reader->crdr_data, sizeof(struct pcsc_data))) { return ERROR; } struct pcsc_data *crdr_data = pcsc_reader->crdr_data; crdr_data->hContext = hContext; // here we need to list the pcsc readers and get the name from there, // the pcsc_reader->device should contain the pcsc_reader number // and after the actual device name is copied in crdr_data->pcsc_name . rv = SCardListReaders(crdr_data->hContext, NULL, NULL, &dwReaders); if(rv != SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [1] : (%lx)", (unsigned long)rv); return ERROR; } if(!cs_malloc(&mszReaders, dwReaders)) { return ERROR; } rv = SCardListReaders(crdr_data->hContext, NULL, mszReaders, &dwReaders); if(rv != SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [2]: (%lx)", (unsigned long)rv); NULLFREE(mszReaders); return ERROR; } /* Extract readers from the null separated string and get the total * number of readers */ nbReaders = 0; ptr = mszReaders; while(*ptr != '\0') { ptr += strlen(ptr) + 1; nbReaders++; } if(nbReaders == 0) { rdr_log(pcsc_reader, "PCSC : no pcsc_reader found"); NULLFREE(mszReaders); return ERROR; } if(!cs_malloc(&readers, nbReaders * sizeof(char *))) { NULLFREE(mszReaders); return ERROR; } /* fill the readers table */ nbReaders = 0; ptr = mszReaders; while(*ptr != '\0') { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %d: %s", nbReaders, ptr); readers[nbReaders] = ptr; ptr += strlen(ptr) + 1; nbReaders++; } reader_nb = atoi((const char *)&pcsc_reader->device); if(reader_nb < 0 || reader_nb >= nbReaders) { rdr_log(pcsc_reader, "Wrong pcsc_reader index: %d", reader_nb); NULLFREE(mszReaders); NULLFREE(readers); return ERROR; } if (readers) { snprintf(crdr_data->pcsc_name, sizeof(crdr_data->pcsc_name), "%s", readers[reader_nb]); NULLFREE(readers); } NULLFREE(mszReaders); } else { rdr_log(pcsc_reader, "PCSC failed establish context (%lx)", (unsigned long)rv); return ERROR; } return OK; }
int32_t init_srvid(void) { FILE *fp = open_config_file(cs_srid); if(!fp) { return 0; } int32_t nr = 0, i; char *payload, *tmp, *saveptr1 = NULL, *token; if(!cs_malloc(&token, MAXLINESIZE)) { return 0; } struct s_srvid *srvid = NULL, *new_cfg_srvid[16], *last_srvid[16]; // A cache for strings within srvids. A checksum is calculated which is the start point in the array (some kind of primitive hash algo). // From this point, a sequential search is done. This greatly reduces the amount of string comparisons. char **stringcache[1024]; int32_t allocated[1024] = { 0 }; int32_t used[1024] = { 0 }; struct timeb ts, te; cs_ftime(&ts); memset(last_srvid, 0, sizeof(last_srvid)); memset(new_cfg_srvid, 0, sizeof(new_cfg_srvid)); while(fgets(token, MAXLINESIZE, fp)) { int32_t l, j, len = 0, len2, srvidtmp; uint32_t pos; char *srvidasc; tmp = trim(token); if(tmp[0] == '#') { continue; } if((l = strlen(tmp)) < 6) { continue; } if(!(srvidasc = strchr(token, ':'))) { continue; } if(!(payload = strchr(token, '|'))) { continue; } *payload++ = '\0'; if(!cs_malloc(&srvid, sizeof(struct s_srvid))) { NULLFREE(token); fclose(fp); return (1); } char tmptxt[128]; int32_t offset[4] = { -1, -1, -1, -1 }; char *ptr1, *searchptr[4] = { NULL, NULL, NULL, NULL }; char **ptrs[4] = { &srvid->prov, &srvid->name, &srvid->type, &srvid->desc }; for(i = 0, ptr1 = strtok_r(payload, "|", &saveptr1); ptr1 && (i < 4) ; ptr1 = strtok_r(NULL, "|", &saveptr1), ++i) { // check if string is in cache len2 = strlen(ptr1); pos = 0; for(j = 0; j < len2; ++j) { pos += (uint8_t)ptr1[j]; } pos = pos % 1024; for(j = 0; j < used[pos]; ++j) { if(!strcmp(stringcache[pos][j], ptr1)) { searchptr[i] = stringcache[pos][j]; break; } } if(searchptr[i]) { continue; } offset[i] = len; cs_strncpy(tmptxt + len, trim(ptr1), sizeof(tmptxt) - len); len += strlen(ptr1) + 1; } char *tmpptr = NULL; if(len > 0 && !cs_malloc(&tmpptr, len)) { continue; } srvid->data = tmpptr; if(len > 0) { memcpy(tmpptr, tmptxt, len); } for(i = 0; i < 4; i++) { if(searchptr[i]) { *ptrs[i] = searchptr[i]; continue; } if(offset[i] > -1) { *ptrs[i] = tmpptr + offset[i]; // store string in stringcache tmp = *ptrs[i]; len2 = strlen(tmp); pos = 0; for(j = 0; j < len2; ++j) { pos += (uint8_t)tmp[j]; } pos = pos % 1024; if(used[pos] >= allocated[pos]) { if(allocated[pos] == 0) { if(!cs_malloc(&stringcache[pos], 16 * sizeof(char *))) { break; } } else { if(!cs_realloc(&stringcache[pos], (allocated[pos] + 16) * sizeof(char *))) { break; } } allocated[pos] += 16; } stringcache[pos][used[pos]] = tmp; used[pos] += 1; } } *srvidasc++ = '\0'; srvidtmp = dyn_word_atob(srvidasc) & 0xFFFF; //printf("srvid %s - %d\n",srvidasc,srvid->srvid ); if(srvidtmp < 0) { NULLFREE(tmpptr); NULLFREE(srvid); continue; } else { srvid->srvid = srvidtmp; } srvid->ncaid = 0; for(i = 0, ptr1 = strtok_r(token, ",", &saveptr1); (ptr1) && (i < 10) ; ptr1 = strtok_r(NULL, ",", &saveptr1), i++) { srvid->caid[i] = dyn_word_atob(ptr1); srvid->ncaid = i + 1; //cs_debug_mask(D_CLIENT, "ld caid: %04X srvid: %04X Prov: %s Chan: %s",srvid->caid[i],srvid->srvid,srvid->prov,srvid->name); } nr++; if(new_cfg_srvid[srvid->srvid >> 12]) { last_srvid[srvid->srvid >> 12]->next = srvid; } else { new_cfg_srvid[srvid->srvid >> 12] = srvid; } last_srvid[srvid->srvid >> 12] = srvid; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; #if USE_ITER_API static #endif cs_insn *insn = NULL; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret = cs_open (CS_ARCH_X86, mode, &handle); int regsz = 4; if (ret != CS_ERR_OK) { return 0; } switch (a->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: case 32: regsz = 4; break; } memset (op, '\0', sizeof (RAnalOp)); op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->src[0] = NULL; op->src[1] = NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next #if USE_ITER_API { ut64 naddr = addr; size_t size = len; if (insn == NULL) insn = cs_malloc (handle); n = cs_disasm_iter (handle, (const uint8_t**)&buf, &size, (uint64_t*)&naddr, insn); } #else n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); #endif if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp"; op->size = insn->size; op->prefix = 0; switch (insn->detail->x86.prefix[0]) { case X86_PREFIX_REPNE: op->prefix |= R_ANAL_OP_PREFIX_REPNE; case X86_PREFIX_REP: op->prefix |= R_ANAL_OP_PREFIX_REP; case X86_PREFIX_LOCK: op->prefix |= R_ANAL_OP_PREFIX_LOCK; } switch (insn->id) { case X86_INS_FNOP: case X86_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ","); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_CLI: case X86_INS_STI: case X86_INS_CLC: case X86_INS_STC: break; // cmov case X86_INS_CMOVA: case X86_INS_CMOVAE: case X86_INS_CMOVB: case X86_INS_CMOVBE: case X86_INS_FCMOVBE: case X86_INS_FCMOVB: case X86_INS_CMOVE: case X86_INS_FCMOVE: case X86_INS_CMOVG: case X86_INS_CMOVGE: case X86_INS_CMOVL: case X86_INS_CMOVLE: case X86_INS_FCMOVNBE: case X86_INS_FCMOVNB: case X86_INS_CMOVNE: case X86_INS_FCMOVNE: case X86_INS_CMOVNO: case X86_INS_CMOVNP: case X86_INS_FCMOVNU: case X86_INS_CMOVNS: case X86_INS_CMOVO: case X86_INS_CMOVP: case X86_INS_FCMOVU: case X86_INS_CMOVS: // mov case X86_INS_MOV: case X86_INS_MOVZX: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSS: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: { op->type = R_ANAL_OP_TYPE_MOV; switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 1); esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } break; default: if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,=", src, dst); free (src); free (dst); } break; } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } } break; case X86_INS_SHL: case X86_INS_SHLD: case X86_INS_SHLX: op->type = R_ANAL_OP_TYPE_SHL; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,<<=,cz,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAR: case X86_INS_SARX: op->type = R_ANAL_OP_TYPE_SAR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,>>=,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAL: case X86_INS_SALC: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,<<=,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SHR: case X86_INS_SHRD: case X86_INS_SHRX: op->type = R_ANAL_OP_TYPE_SHR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,>>=,cz,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_CMP: case X86_INS_VCMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: op->type = R_ANAL_OP_TYPE_CMP; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,==,%%z,zf,=", src, dst); free (src); free (dst); } switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; default: switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; case X86_OP_IMM: op->ptr = INSOP(1).imm; break; default: break; } break; } break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; if (a->decode) { char *src = getarg (handle, insn, 0, 0); char *dst = getarg (handle, insn, 1, 2); esilprintf (op, "%s,%s,=", dst, src); free (src); free (dst); } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; switch (INSOP(1).mem.base) { case X86_REG_RIP: op->ptr += addr + op->size; break; case X86_REG_RBP: case X86_REG_EBP: op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; break; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: { char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%d,%s,-=,%s,%s,=[%d]", rs, sp, dst, sp, rs); free (dst); } switch (INSOP(0).type) { case X86_OP_IMM: op->ptr = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_PUSH; break; default: op->type = R_ANAL_OP_TYPE_UPUSH; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case X86_INS_LEAVE: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { esilprintf (op, "%s,%s,=,%s,[%d],%s,%d,%s,-=", bp, sp, sp, rs, bp, rs, sp); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_POP: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPF: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, dst, rs, sp); free (dst); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_INT: if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_INT1: case X86_INS_INT3: case X86_INS_INTO: case X86_INS_VMCALL: case X86_INS_VMMCALL: case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JRCXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: case X86_INS_LOOP: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; if (a->decode) { char *dst = getarg (handle, insn, 0, 2); switch (insn->id) { case X86_INS_JL: esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JLE: esilprintf (op, "of,sf,^,zf,|,%s,%s,=", dst, pc); break; case X86_INS_JA: esilprintf (op, "cf,!,zf,!,&,?{,%s,%s,=,}",dst, pc); break; case X86_INS_JAE: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JB: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JO: esilprintf (op, "of,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNO: esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JE: esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JGE: esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNE: esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JG: esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JS: esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNS: esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JP: esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNP: esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JBE: esilprintf (op, "zf,cf,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JCXZ: esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JECXZ: esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JRCXZ: esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc); break; } free (dst); } break; case X86_INS_CALL: case X86_INS_LCALL: switch (INSOP(0).type) { case X86_OP_IMM: op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; if (INSOP(0).mem.base == 0) { op->ptr = INSOP(0).mem.disp; } break; default: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; break; } if (a->decode) { char* arg = getarg (handle, insn, 0, 1); esilprintf (op, "%d,%s,+," "%d,%s,-=,%s," "=[]," "%s,%s,=", op->size, pc, rs, sp, sp, arg, pc); free (arg); } break; case X86_INS_JMP: case X86_INS_LJMP: if (a->decode) { char *src = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,=", src, pc); free (src); } // TODO: what if UJMP? if (INSOP(0).type == X86_OP_IMM) { op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } } else { op->type = R_ANAL_OP_TYPE_UJMP; } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,^=", src, dst); free (src); free (dst); } break; case X86_INS_OR: op->type = R_ANAL_OP_TYPE_OR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,|=", src, dst); free (src); free (dst); } break; case X86_INS_SUB: case X86_INS_DEC: case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,-=,%%c,cf,=,%%z,zf,=,%%s,sf,=,%%o,of,=", src, dst); // TODO: update flags free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = INSOP(1).imm; } } break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,&=", src, dst); free (src); free (dst); } break; case X86_INS_DIV: op->type = R_ANAL_OP_TYPE_DIV; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,/=", src, dst); free (src); free (dst); } break; case X86_INS_MUL: op->type = R_ANAL_OP_TYPE_MUL; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,*=", src, dst); free (src); free (dst); } break; case X86_INS_INC: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "1,%s,+=", dst); free (dst); } break; case X86_INS_ADD: case X86_INS_FADD: case X86_INS_ADDPD: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,+=", src, dst); free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -INSOP(1).imm; } } break; } } #if !USE_ITER_API cs_free (insn, n); #endif cs_close (&handle); return op->size; }
int32_t init_config(void) { FILE *fp; if(config_enabled(WEBIF)) { fp = open_config_file(cs_conf); } else { fp = open_config_file_or_die(cs_conf); } const struct config_sections *cur_section = oscam_conf; // Global char *token; config_sections_set_defaults(oscam_conf, &cfg); if(!fp) { // no oscam.conf but webif is included in build, set it up for lan access and tweak defaults #ifdef WEBIF cfg.http_port = DEFAULT_HTTP_PORT; chk_iprange(cs_strdup(DEFAULT_HTTP_ALLOW), &cfg.http_allowed); #endif NULLFREE(cfg.logfile); cfg.logtostdout = 1; #ifdef HAVE_DVBAPI cfg.dvbapi_enabled = 1; #endif return 0; } if(!cs_malloc(&token, MAXLINESIZE)) { return 1; } int line = 0; int valid_section = 1; while(fgets(token, MAXLINESIZE, fp)) { ++line; int len = strlen(trim(token)); if(len < 3) // a=b or [a] are at least 3 chars { continue; } if(token[0] == '#') // Skip comments { continue; } if(token[0] == '[' && token[len - 1] == ']') { token[len - 1] = '\0'; valid_section = 0; const struct config_sections *newconf = config_find_section(oscam_conf, token + 1); if(config_section_is_active(newconf) && cur_section) { config_list_apply_fixups(cur_section->config, &cfg); cur_section = newconf; valid_section = 1; } if(!newconf) { fprintf(stderr, "WARNING: %s line %d unknown section [%s].\n", cs_conf, line, token + 1); continue; } if(!config_section_is_active(newconf)) { fprintf(stderr, "WARNING: %s line %d section [%s] is ignored (support not compiled in).\n", cs_conf, line, newconf->section); } continue; } if(!valid_section) { continue; } char *value = strchr(token, '='); if(!value) // No = found, well go on { continue; } *value++ = '\0'; char *tvalue = trim(value); char *ttoken = trim(strtolower(token)); if(cur_section && !config_list_parse(cur_section->config, ttoken, tvalue, &cfg)) { fprintf(stderr, "WARNING: %s line %d section [%s] contains unknown setting '%s=%s'\n", cs_conf, line, cur_section->section, ttoken, tvalue); } } free(token); fclose(fp); if(cur_section) { config_list_apply_fixups(cur_section->config, &cfg); } return 0; }
/* * This function returns cw (mostly received) in cache for er, or NULL if not found. * IMPORTANT: * - If found, DON'T forget to free returned ecm, because it is a copy useful to get data * - If found, and cacheex_src client of returned ecm is not NULL, and we want to access it, * remember to check for its validity (client structure is still existent) * E.g.: if(ecm->cacheex_src && is_valid_client(ecm->cacheex_src) && !ecm->cacheex_src->kill) * We don't want make this stuff here to avoid useless cpu time if outside function we would not access to it. */ struct ecm_request_t *check_cache(ECM_REQUEST *er, struct s_client *cl) { if(!er->csp_hash) return NULL; ECM_REQUEST *ecm = NULL; ECMHASH *result; CW *cw; uint64_t grp = cl?cl->grp:0; pthread_rwlock_rdlock(&cache_lock); result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t),&compare_csp_hash); cw = get_first_cw(result, er); if( cw && ( cw->csp //csp have no grp! || !grp //csp client(no grp) searching for cache || ( grp && cw->grp //ecm group --> only when readers/ex-clients answer (e_found) it && (grp & cw->grp) ) ) ){ #ifdef CS_CACHEEX //if preferlocalcards=2 for this ecm request, we can server ONLY cw from localcards readers until stage<3 if(er->preferlocalcards==2 && !cw->localcards && er->stage<3){ pthread_rwlock_unlock(&cache_lock); return NULL; } CWCHECK check_cw = get_cwcheck(er); if((!cw->proxy && !cw->localcards) //cw received from ONLY cacheex/csp peers && check_cw.counter>1 && cw->count < check_cw.counter && (check_cw.mode || !er->cacheex_wait_time_expired) ){ pthread_rwlock_unlock(&cache_lock); return NULL; } #endif #ifdef CW_CYCLE_CHECK uint8_t cwc_ct = cw->cwc_cycletime > 0 ? cw->cwc_cycletime : 0; uint8_t cwc_ncwc = cw->cwc_next_cw_cycle < 2 ? cw->cwc_next_cw_cycle : 2; if(cw->got_bad_cwc) { pthread_rwlock_unlock(&cache_lock); return NULL; } if(checkcwcycle(cl, er, NULL, cw->cw, 0, cwc_ct, cwc_ncwc) != 0){ cs_debug_mask(D_CWC | D_LB, "{client %s, caid %04X, srvid %04X} [check_cache] cyclecheck passed ecm in INT. cache, ecm->rc %d", (cl ? cl->account->usr : "******"), er->caid, er->srvid, ecm ? ecm->rc : -1); }else{ cs_debug_mask(D_CWC, "cyclecheck [BAD CW Cycle] from Int. Cache detected.. {client %s, caid %04X, srvid %04X} [check_cache] -> skip cache answer", (cl ? cl->account->usr : "******"), er->caid, er->srvid); cw->got_bad_cwc = 1; // no need to check it again pthread_rwlock_unlock(&cache_lock); return NULL; } #endif if (cs_malloc(&ecm, sizeof(ECM_REQUEST))){ ecm->rc = E_FOUND; ecm->rcEx = 0; memcpy(ecm->cw, cw->cw, 16); ecm->grp = cw->grp; ecm->selected_reader = cw->selected_reader; ecm->cwc_cycletime = cw->cwc_cycletime; ecm->cwc_next_cw_cycle = cw->cwc_next_cw_cycle; #ifdef CS_CACHEEX ecm->cacheex_src = cw->cacheex_src; #endif ecm->cw_count = cw->count; } } pthread_rwlock_unlock(&cache_lock); return ecm; }
int32_t disas_executable_and_examine(void) { int32_t rtrn; uint64_t file_size; uint32_t count = 0; int32_t file auto_close = 0; char *file_buffer = NULL; char *exec_path auto_free = NULL; /* Ask the file module for the path of the binary to test. */ rtrn = get_exec_path(&exec_path); if(rtrn < 0) { output(ERROR, "Can't get exec path\n"); return -1; } /* Open the target binary. */ file = open(exec_path, O_RDONLY); if(file < 0) { output(ERROR, "open: %s\n", strerror(errno)); return (-1); } /* Read file in to memory. */ rtrn = map_file_in(file, &file_buffer, &file_size, READ); if(rtrn < 0) { output(ERROR, "Can't memory map file\n"); return (-1); } /* Create a const pointer to the file buffer so we can avoid a warning when using cs_disasm_iter(). */ const uint8_t *file_buffer_copy = (uint8_t *)file_buffer; /* Create capstone handle.*/ csh handle; cs_open(CS_ARCH_X86, CS_MODE_32, &handle); /* Allocate memory cache for 1 instruction, to be used by cs_disasm_iter later. */ cs_insn *insn = cs_malloc(handle); uint64_t address = 0; /* Disassemble one instruction at a time & store the result into the insn variable above */ while(cs_disasm_iter(handle, (const uint8_t **)&file_buffer_copy, (unsigned long *)&file_size, &address, insn)) { /* Check for branchs in the disasembly, maybe switch to a hash map in the future. */ if(strncmp(insn->mnemonic, "jne", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "je", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jg", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jle", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jl", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jge", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jo", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jno", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "js", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jns", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jz", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jb", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jnae", 4) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jc", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jnb", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jae", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jnc", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jbe", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jna", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "ja", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jnbe", 4) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jl", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jnge", 4) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jge", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jng", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jnle", 4) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jp", 2) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jpe", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jnp", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jpo", 3) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jcxz", 4) == 0) { goto found_branch; } else if(strncmp(insn->mnemonic, "jecxz", 5) == 0) { goto found_branch; } else { /* We didn't find a branch instruction so cotinue looping */ continue; } found_branch: /*map->exec_ctx->address_index = realloc(map->exec_ctx->address_index, sizeof(char *) * count); if(map->exec_ctx->address_index == NULL) { output(ERROR, "Can't realloc address index: %s\n", strerror(errno)); return -1; } rtrn = asprintf(&map->exec_ctx->address_index[count], "%s", insn->address); if(rtrn < 0) { output(ERROR, "Can't alloc address index slot: %s\n", strerror(errno)); return -1; } */ count++; continue; } /* Save the offset of where the program ends. */ rtrn = set_end_offset(insn[0].address); if(rtrn < 0) { output(ERROR, "Can't set end offset\n"); return -1; } cs_free(insn, 1); // release the cache memory when done munmap(file_buffer, (size_t)file_size); return 0; }
static void ecmheaderwhitelist_fn(const char *token, char *value, void *setting, FILE *f) { struct s_reader *rdr = setting; if (value) { char *ptr, *ptr2, *ptr3; struct s_ecmHeaderwhitelist *tmp, *last = NULL; if (strlen(value) == 0) { for (tmp = rdr->ecmHeaderwhitelist; tmp; tmp=tmp->next) add_garbage(tmp); rdr->ecmHeaderwhitelist = NULL; } else { char *ptr4, *ptr5, *ptr6, *saveptr = NULL, *saveptr4 = NULL, *saveptr5 = NULL, *saveptr6 = NULL; uint16_t caid = 0; uint32_t provid = 0; int16_t len = 0; for (ptr = strtok_r(value, ";", &saveptr); ptr; ptr = strtok_r(NULL, ";", &saveptr)) { caid = 0; provid = 0; ptr2 = strchr(ptr, '@'); ptr3 = strchr(ptr, ':'); if (ptr2 == NULL && ptr3 == NULL) { //no Caid no Provid for (ptr4 = strtok_r(ptr, ",", &saveptr4); ptr4; ptr4 = strtok_r(NULL, ",", &saveptr4)) { if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) { ptr4 = trim(ptr4); len = strlen(ptr4); key_atob_l(ptr4, tmp->header, len); tmp->len = len; tmp->caid = 0; tmp->provid = 0; tmp->next = NULL; if (last == NULL) { rdr->ecmHeaderwhitelist = tmp; } else { last->next = tmp; } last = tmp; } } } if (ptr3 != NULL && ptr2 == NULL) { // only with Caid ptr3[0] = '\0'; ++ptr3; caid = (int16_t)dyn_word_atob(ptr); for (ptr5 = strtok_r(ptr3, ",", &saveptr5); ptr5; ptr5 = strtok_r(NULL, ",", &saveptr5)) { if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) { tmp->caid = caid; tmp->provid = 0; ptr5 = trim(ptr5); len = strlen(ptr5); key_atob_l(ptr5, tmp->header, len); tmp->len = len; tmp->next = NULL; if (last == NULL) { rdr->ecmHeaderwhitelist = tmp; } else { last->next = tmp; } last = tmp; } } } if (ptr3 != NULL && ptr2 != NULL) { // with Caid & Provid ptr2[0] = '\0'; ++ptr2; // -> provid ptr3[0] = '\0'; ++ptr3; // -> headers caid = (int16_t)dyn_word_atob(ptr); provid = (uint32_t)a2i(ptr2, 6); for (ptr6 = strtok_r(ptr3, ",", &saveptr6); ptr6; ptr6 = strtok_r(NULL, ",", &saveptr6)) { if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) { tmp->caid = caid; tmp->provid = provid; ptr6 = trim(ptr6); len = strlen(ptr6); key_atob_l(ptr6, tmp->header, len); tmp->len = len; tmp->next = NULL; if (last == NULL) { rdr->ecmHeaderwhitelist = tmp; } else { last->next = tmp; } last = tmp; } } } } } /* if (rdr->ecmHeaderwhitelist != NULL) { // debug cs_log("**********Begin ECM Header List for Reader: %s **************", rdr->label); struct s_ecmHeaderwhitelist *tmp; for(tmp = rdr->ecmHeaderwhitelist; tmp; tmp=tmp->next){ cs_log("Caid: %i Provid: %i Header: %02X Len: %i", tmp->caid, tmp->provid, tmp->header[0], tmp->len); } cs_log("***********End ECM Header List for Reader: %s ***************", rdr->label); } */ return; } value = mk_t_ecmheaderwhitelist(rdr->ecmHeaderwhitelist); if (strlen(value) > 0 || cfg.http_full_cfg) fprintf_conf(f, token, "%s\n", value); free_mk_t(value); }