示例#1
0
static int32_t cs_check_v(IN_ADDR_T ip, int32_t port, int32_t add, char *info, int32_t acosc_penalty_duration)
{
	int32_t result = 0;
	bool acosc_enabled = false;

#ifdef CS_ANTICASC
	if(cfg.acosc_enabled)
		acosc_enabled = true;
#endif

	if(!(cfg.failbantime || acosc_enabled))
		{ return 0; }

	if(!cfg.v_list)
		{ cfg.v_list = ll_create("v_list"); }

	struct timeb (now);
	cs_ftime(&now);
	LL_ITER itr = ll_iter_create(cfg.v_list);
	V_BAN *v_ban_entry;
	int32_t ftime = cfg.failbantime * 60 * 1000;

	//run over all banned entries to do housekeeping:
	while((v_ban_entry = ll_iter_next(&itr)))
	{
		// housekeeping:
		int32_t gone = comp_timeb(&now, &v_ban_entry->v_time);
		if(((gone >= ftime) && !v_ban_entry->acosc_entry) || (v_ban_entry->acosc_entry && ((gone/1000) >= v_ban_entry->acosc_penalty_dur))) // entry out of time->remove
		{
			NULLFREE(v_ban_entry->info);
			ll_iter_remove_data(&itr);
			continue;
		}

		if(IP_EQUAL(ip, v_ban_entry->v_ip) && port == v_ban_entry->v_port)
		{
			result = 1;
			if(!info)
				{ info = v_ban_entry->info; }
			else if(!v_ban_entry->info)
			{
				v_ban_entry->info = cs_strdup(info);
			}

			if(!add)
			{
				if(v_ban_entry->v_count >= cfg.failbancount)
				{
					if(!v_ban_entry->acosc_entry)
                    	{ cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - %d seconds left%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (ftime - gone)/1000, info ? ", info: " : "", info ? info : ""); }
					else
						{ cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - %d seconds left%s%s", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, (v_ban_entry->acosc_penalty_dur - (gone/1000)), info?", info: ":"", info?info:""); }

				}
				else
				{
					cs_debug_mask(D_TRACE, "failban: ip %s:%d chance %d of %d%s%s",
								  cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port,
								  v_ban_entry->v_count, cfg.failbancount, info ? ", info: " : "", info ? info : "");
					v_ban_entry->v_count++;
				}
			}
			else
			{
				cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - already exist in list%s%s",
							  cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, info ? ", info: " : "", info ? info : "");
			}
		}
	}

	if(add && !result)
	{
		if(cs_malloc(&v_ban_entry, sizeof(V_BAN)))
		{
			cs_ftime(&v_ban_entry->v_time);
			v_ban_entry->v_ip = ip;
			v_ban_entry->v_port = port;
			v_ban_entry->v_count = 1;
			v_ban_entry->acosc_entry = false;
			v_ban_entry->acosc_penalty_dur = 0;
			if(acosc_penalty_duration > 0)
			{
				v_ban_entry->v_count = cfg.failbancount +1; // set it to a higher level
				v_ban_entry->acosc_entry = true;
				v_ban_entry->acosc_penalty_dur = acosc_penalty_duration;
			}
			if(info)
				{ v_ban_entry->info = cs_strdup(info); }
			ll_iter_insert(&itr, v_ban_entry);
			cs_debug_mask(D_TRACE, "failban: ban ip %s:%d with timestamp %ld%s%s",
						  cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, v_ban_entry->v_time.time,
						  info ? ", info: " : "", info ? info : "");
		}
	}

	return result;
}
示例#2
0
int32_t radegast_cli_init(struct s_client *cl)
{
  *cl = *cl; //prevent compiler warning
  struct sockaddr_in loc_sa;
  int32_t handle;

  cur_client()->pfd=0;
  if (cur_client()->reader->r_port<=0)
  {
    cs_log("radegast: invalid port %d for server %s", cur_client()->reader->r_port, cur_client()->reader->device);
    return(1);
  }

  cur_client()->ip=0;
  memset((char *)&loc_sa,0,sizeof(loc_sa));
  loc_sa.sin_family = AF_INET;
#ifdef LALL
  if (cfg.serverip[0])
    loc_sa.sin_addr.s_addr = inet_addr(cfg.serverip);
  else
#endif
    loc_sa.sin_addr.s_addr = INADDR_ANY;
  loc_sa.sin_port = htons(cur_client()->reader->l_port);

  if ((cur_client()->udp_fd=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
  {
    cs_log("radegast: Socket creation failed (errno=%d %s)", errno, strerror(errno));
    cs_exit(1);
  }

#ifdef SO_PRIORITY
  if (cfg.netprio)
    setsockopt(cur_client()->udp_fd, SOL_SOCKET, SO_PRIORITY,
               (void *)&cfg.netprio, sizeof(uintptr_t));
#endif
  if (!cur_client()->reader->tcp_ito) {
    uint32_t keep_alive = cur_client()->reader->tcp_ito?1:0;
    setsockopt(cur_client()->udp_fd, SOL_SOCKET, SO_KEEPALIVE,
    (void *)&keep_alive, sizeof(uintptr_t));
  }

  memset((char *)&cur_client()->udp_sa,0,sizeof(cur_client()->udp_sa));
  cur_client()->udp_sa.sin_family = AF_INET;
  cur_client()->udp_sa.sin_port = htons((uint16_t)cur_client()->reader->r_port);

  cs_log("radegast: proxy %s:%d (fd=%d)",
  cur_client()->reader->device, cur_client()->reader->r_port, cur_client()->udp_fd);

  handle = network_tcp_connection_open();
  if(handle < 0) return -1;

  cur_client()->reader->tcp_connected = 2;
  cur_client()->reader->card_status = CARD_INSERTED;
  cur_client()->reader->last_g = cur_client()->reader->last_s = time((time_t *)0);

  cs_debug_mask(D_CLIENT, "radegast: last_s=%d, last_g=%d", cur_client()->reader->last_s, cur_client()->reader->last_g);

  cur_client()->pfd=cur_client()->udp_fd;

  return(0);
}
示例#3
0
int32_t ICC_Async_Device_Init (struct s_reader *reader)
{
	reader->fdmc=-1;
	cs_debug_mask (D_IFD, "IFD: Opening device %s\n", reader->device);

	reader->written = 0;

	if (reader->crdr.active==1 && reader->crdr.reader_init) {
		return reader->crdr.reader_init(reader);
	}

	switch(reader->typ) {
		case R_SC8in1:
			cs_writelock(&sc8in1_lock);
			if (reader->handle != 0) {//this reader is already initialized
				cs_writeunlock(&sc8in1_lock);
				return OK;
			}

			//this reader is uninitialized, thus the first one, since the first one initializes all others

			//get physical device name
			int32_t pos = strlen(reader->device)-2; //this is where : should be located; is also valid length of physical device name
			if (reader->device[pos] != 0x3a) //0x3a = ":"
				cs_log("ERROR: '%c' detected instead of slot separator `:` at second to last position of device %s", reader->device[pos], reader->device);
			reader->slot=(int)reader->device[pos+1] - 0x30;
			reader->device[pos]= 0; //slot 1 reader now gets correct physicalname

			//open physical device
			reader->handle = open (reader->device,  O_RDWR | O_NOCTTY| O_NONBLOCK);
			if (reader->handle < 0) {
				cs_log("ERROR opening device %s",reader->device);
				cs_writeunlock(&sc8in1_lock);
				return ERROR;
			}

			//copy physical device name and file handle to other slots
			struct s_reader *rdr;
			LL_ITER itr = ll_iter_create(configured_readers);
			while((rdr = ll_iter_next(&itr))) //copy handle to other slots
				if (rdr->typ == R_SC8in1 && rdr != reader) { //we have another sc8in1 reader
					unsigned char save = rdr->device[pos];
					rdr->device[pos]=0; //set to 0 so we can compare device names
					if (!strcmp(reader->device, rdr->device)) {//we have a match to another slot with same device name
						rdr->handle = reader->handle;
						rdr->slot=(int)rdr->device[pos+1] - 0x30;
					}
					else
						rdr->device[pos] = save; //restore character
				}
			break;
		case R_MP35:
		case R_MOUSE:
			reader->handle = open (reader->device,  O_RDWR | O_NOCTTY| O_NONBLOCK);
			if (reader->handle < 0) {
				cs_log("ERROR opening device %s",reader->device);
				return ERROR;
			}
			break;
#if defined(TUXBOX) && defined(PPC)
		case R_DB2COM1:
		case R_DB2COM2:
			reader->handle = open (reader->device,  O_RDWR | O_NOCTTY| O_SYNC);
			if (reader->handle < 0) {
				cs_log("ERROR opening device %s",reader->device);
				return ERROR;
			}
			if ((reader->fdmc = open(DEV_MULTICAM, O_RDWR)) < 0) {
				close(reader->handle);
				cs_log("ERROR opening device %s",DEV_MULTICAM);
				return ERROR;
			}
			break;
#endif
		case R_SMART:
#if defined(LIBUSB)
			call (SR_Init(reader));
			break;
#else
			cs_log("ERROR, you have specified 'protocol = smartreader' in oscam.server,");
			cs_log("recompile with SmartReader support.");
			return ERROR;
#endif
		case R_INTERNAL:
#if defined(COOL) || defined(SU980)
			return Cool_Init(reader);
#elif defined(AZBOX)
			return Azbox_Init(reader);
#elif defined(SCI_DEV)
	#if defined(SH4) || defined(STB04SCI)
			reader->handle = open (reader->device, O_RDWR|O_NONBLOCK|O_NOCTTY);
	#else
			reader->handle = open (reader->device, O_RDWR);
	#endif
			if (reader->handle < 0) {
				cs_log("ERROR opening device %s",reader->device);
				return ERROR;
			}
#elif defined(WITH_STAPI)
			return STReader_Open(reader->device, &reader->stsmart_handle);
#else//SCI_DEV
			cs_log("ERROR, you have specified 'protocol = internal' in oscam.server,");
			cs_log("recompile with internal reader support.");
			return ERROR;
#endif//SCI_DEV
			break;
#ifdef HAVE_PCSC
		case R_PCSC:
			return (pcsc_reader_init(reader, reader->device));
			break;
#endif
		default:
			cs_log("ERROR ICC_Device_Init: unknow reader type %i",reader->typ);
			return ERROR;
	}

	if (reader->typ == R_MP35)
	{
		if (MP35_Init(reader)) {
				cs_log("ERROR: MP35_Init returns error");
				MP35_Close (reader);
				return ERROR;
		}
	}
	else if (reader->typ <= R_MOUSE)
		if (Phoenix_Init(reader)) {
				cs_log("ERROR: Phoenix_Init returns error");
				Phoenix_Close (reader);
				return ERROR;
		}

	if (reader->typ == R_SC8in1) {
		call(Sc8in1_Init(reader));
		cs_writeunlock(&sc8in1_lock);
	}

 cs_debug_mask (D_IFD, "IFD: Device %s succesfully opened\n", reader->device);
 return OK;
}
示例#4
0
static int32_t oscam_ser_recv(struct s_client *client, uchar *xbuf, int32_t l)
{
	int32_t s, p, n, r;
	uchar job = IS_BAD;
	static uchar lb;
	static int32_t have_lb = 0;
	uchar *buf = xbuf + 1;
	struct s_serial_client *serialdata = client->serialdata;

	if(!client->pfd) { return (-1); }
	cs_ftime(&serialdata->tps);
	serialdata->tpe = serialdata->tps;
	serialdata->tpe.millitm += serialdata->oscam_ser_timeout;
	serialdata->tpe.time += (serialdata->tpe.millitm / 1000);
	serialdata->tpe.millitm %= 1000;
	buf[0] = lb;
	for(s = p = r = 0, n = have_lb; (s < 4) && (p >= 0); s++)
	{
		switch(s)
		{
		case 0:       // STAGE 0: skip known garbage from DSR9500
			if(oscam_ser_selrec(buf, 2 - n, l, &n))
			{
				if((buf[0] == 0x0A) && (buf[1] == 0x0D))
					{ p = (-4); }
				if((buf[0] == 0x0D) && (buf[1] == 0x0A))
					{ p = (-4); }
			}
			else
				{ p = (-3); }
			have_lb = 0;
			break;
		case 1:       // STAGE 1: identify protocol
			p = (-3);
			if(oscam_ser_selrec(buf, 1, l, &n))  // now we have 3 bytes in buf
			{
				if((buf[0] == 0x04) && (buf[1] == 0x00) && (buf[2] == 0x02))    //skip unsupported Advanced Serial Sharing Protocol HF 8900
				{
					oscam_ser_selrec(buf, 2, l, &n); // get rest 2 bytes to buffor
					p = (-4);
					have_lb = 0;
					break;
				}
				else
				{

					p = (-2);
					if(client->typ == 'c')       // HERE IS SERVER
					{
						job = IS_ECM;   // assume ECM
						switch(buf[0])
						{
						case 0x00:
							if((buf[1] == 0x01) && (buf[2] == 0x00))
							{
								p = P_GS;
								job = IS_LGO;
								serialdata->tpe.time++;
							}
							break;
						case 0x01:
							if((buf[1] & 0xf0) == 0xb0) { p = P_GBOX; }
							else
							{
								p = P_SSSP;
								job = IS_PMT;
							}
							break;  // pmt-request
						case 0x02:
							p = P_HSIC;
							break;
						case 0x03:
							switch(serialdata->oscam_ser_proto)
							{
							case P_SSSP  :
							case P_GS    :
							case P_DSR95 :
								p = serialdata->oscam_ser_proto;
								break;
							case P_AUTO  :
								p = (buf[1] < 0x30) ? P_SSSP : P_DSR95;
								break;    // auto for GS is useless !!
							}
							break;
						case 0x04:
							p = P_DSR95;
							job = IS_ECHO;
							serialdata->dsr9500type = P_DSR_GNUSMAS;
							break;
						case 0x7E:
							p = P_ALPHA;
							if(buf[1] != 0x80) { job = IS_BAD; }
							break;
						case 0x80:
						case 0x81:
							p = P_BOMBA;
							break;
						}
					}

					else                // HERE IS CLIENT
					{
						job = IS_DCW;   // assume DCW
						switch(serialdata->oscam_ser_proto)
						{
						case P_HSIC :
							if((buf[0] == 4) && (buf[1] == 4)) { p = P_HSIC; }
							break;
						case P_BOMBA:
							p = P_BOMBA;
							break;
						case P_DSR95:
							if(buf[0] == 4) { p = P_DSR95; }
							break;
						case P_ALPHA:
							if(buf[0] == 0x88) { p = P_ALPHA; }
							break;
						}
					}
					if((serialdata->oscam_ser_proto != p) && (serialdata->oscam_ser_proto != P_AUTO))
						{ p = (-2); }
				}
			}
			break;
		case 2:       // STAGE 2: examine length
			if(client->typ == 'c') switch(p)
				{
				case P_SSSP  :
					r = (buf[1] << 8) | buf[2];
					break;
				case P_BOMBA :
					r = buf[2];
					break;
				case P_HSIC  :
					if(oscam_ser_selrec(buf, 12, l, &n)) { r = buf[14]; }
					else { p = (-1); }
					break;
				case P_DSR95 :
					if(job == IS_ECHO)
					{
						r = 17 * serialdata->samsung_dcw - 3 + serialdata->samsung_0a;
						serialdata->samsung_dcw = serialdata->samsung_0a = 0;
					}
					else
					{
						if(oscam_ser_selrec(buf, 16, l, &n))
						{
							uchar b;
							if(cs_atob(&b, (char *)buf + 17, 1) < 0)
								{ p = (-2); }
							else
							{
								r = (b << 1);
								r += (serialdata->dsr9500type == P_DSR_WITHSID) ? 4 : 0;
							}
						}
						else { p = (-1); }
					}
					break;
				case P_GS    :
					if(job == IS_LGO)
						{ r = 5; }
					else
					{
						if(oscam_ser_selrec(buf, 1, l, &n))
							{ r = (buf[3] << 8) | buf[2]; }
						else { p = (-1); }
					}
					break;
				case P_ALPHA :
					r = -0x7F; // char specifying EOT
					break;
				case P_GBOX  :
					r = ((buf[1] & 0xf) << 8) | buf[2];
					serialdata->gbox_lens.cat_len = r;
					break;
				default      :
					serialdata->dsr9500type = P_DSR_AUTO;
				}
			else switch(p)
				{
				case P_HSIC   :
					r = (buf[2] == 0x3A) ? 20 : 0;
					break; // 3A=DCW / FC=ECM was wrong
				case P_BOMBA  :
					r = 13;
					break;
				case P_DSR95  :
					r = 14;
					break;
				case P_ALPHA  :
					r = (buf[1] << 8) | buf[2];
					break; // should be 16 always
				}
			break;
		case 3:       // STAGE 3: get the rest ...
			if(r > 0)   // read r additional bytes
			{
				int32_t all = n + r;
				if(!oscam_ser_selrec(buf, r, l, &n))
				{
					cs_debug_mask(D_CLIENT, "not all data received, waiting another 50 ms");
					serialdata->tpe.millitm += 50;
					if(!oscam_ser_selrec(buf, all - n, l, &n))
						{ p = (-1); }
				}
				// auto detect DSR9500 protocol
				if(client->typ == 'c' && p == P_DSR95 && serialdata->dsr9500type == P_DSR_AUTO)
				{
					serialdata->tpe.millitm += 20;
					if(oscam_ser_selrec(buf, 2, l, &n))
					{
						if(cs_atoi((char *)buf + n - 2, 1, 1) == 0xFFFFFFFF)
						{
							switch((buf[n - 2] << 8) | buf[n - 1])
							{
							case 0x0A0D :
								serialdata->dsr9500type = P_DSR_OPEN;
								break;
							case 0x0D0A :
								serialdata->dsr9500type = P_DSR_PIONEER;
								break;
							default     :
								serialdata->dsr9500type = P_DSR_UNKNOWN;
								break;
							}
						}
						else
						{
							if(oscam_ser_selrec(buf, 2, l, &n))
								if(cs_atoi((char *)buf + n - 2, 1, 1) == 0xFFFFFFFF)
									{ serialdata->dsr9500type = P_DSR_UNKNOWN; }
								else
									{ serialdata->dsr9500type = P_DSR_WITHSID; }
							else
							{
								serialdata->dsr9500type = P_DSR_UNKNOWN;
								p = (-1);
							}
						}
					}
					else
						{ serialdata->dsr9500type = P_DSR_GNUSMAS; }
					if(p)
						cs_log("detected dsr9500-%s type receiver",
							   dsrproto_txt[serialdata->dsr9500type]);
				}
				// gbox
				if(client->typ == 'c' && p == P_GBOX)
				{
					int32_t j;
					for(j = 0; (j < 3) && (p > 0); j++)
						switch(j)
						{
						case 0: // PMT head
							if(!oscam_ser_selrec(buf, 3, l, &n))
								{ p = (-1); }
							else if(!(buf[n - 3] == 0x02 && (buf[n - 2] & 0xf0) == 0xb0))
								{ p = (-2); }
							break;
						case 1: // PMT + ECM header
							serialdata->gbox_lens.pmt_len = ((buf[n - 2] & 0xf) << 8) | buf[n - 1];
							if(!oscam_ser_selrec(buf, serialdata->gbox_lens.pmt_len + 3, l, &n))
								{ p = (-1); }
							break;
						case 2: // ECM + ECM PID
							serialdata->gbox_lens.ecm_len = ((buf[n - 2] & 0xf) << 8) | buf[n - 1];
							if(!oscam_ser_selrec(buf, serialdata->gbox_lens.ecm_len + 4, l, &n))
								{ p = (-1); }
						}
				} // gbox
			}
			else if(r < 0)  // read until specified char (-r)
			{
				while((buf[n - 1] != (-r)) && (p > 0))
					if(!oscam_ser_selrec(buf, 1, l, &n))
						{ p = (-1); }
			}
			break;
		}
	}
	if(p == (-2) || p == (-1))
	{
		oscam_ser_selrec(buf, l - n, l, &n); // flush buffer
		serialdata->serial_errors++;
	}
	cs_ftime(&serialdata->tpe);
	cs_ddump_mask(D_CLIENT, buf, n, "received %d bytes from %s in %ld msec", n, remote_txt(),
				  1000 * (serialdata->tpe.time - serialdata->tps.time) + serialdata->tpe.millitm - serialdata->tps.millitm);
	client->last = serialdata->tpe.time;
	switch(p)
	{
	case(-1):
		if(client->typ == 'c' && (n > 2) && (buf[0] == 2) && (buf[1] == 2) && (buf[2] == 2))
		{
			oscam_ser_disconnect();
			cs_log("humax powered on");    // this is nice ;)
		}
		else
		{
			if(client->typ == 'c' && buf[0] == 0x1 && buf[1] == 0x08 && buf[2] == 0x20 && buf[3] == 0x08)
			{
				oscam_ser_disconnect();
				cs_log("ferguson powered on");  // this is nice to ;)
			}
			else
				{ cs_log(incomplete, n); }
		}
		break;
	case(-2):
		cs_debug_mask(D_CLIENT, "unknown request or garbage");
		break;
	}
	xbuf[0] = (uchar)((job << 4) | p);
	return ((p < 0) ? 0 : n + 1);
}
示例#5
0
static int32_t ghttp_capmt_notify(struct s_client *client, struct demux_s *demux)
{
	uchar req[640], lenhdr[64] = "";
	uchar *pids = NULL;
	uchar *end;
	char *encauth = NULL;
	int32_t ret;
	int8_t i, pids_len = 0, offs = 0;
	s_ghttp *context = (s_ghttp *)client->ghttp;

	if(!context) { return -1; }

	cs_debug_mask(D_CLIENT, "%s: capmt %x-%x-%x %d pids on adapter %d mask %x dmx index %d", client->reader->label, demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->adapter_index, demux->ca_mask, demux->demux_index);

	if(demux->ECMpidcount > 0)
	{
		if(cs_malloc(&pids, demux->ECMpidcount * 8))
		{
			pids_len = demux->ECMpidcount * 8;
			for(i = 0; i < demux->ECMpidcount; i++)
			{
				i2b_buf(2, demux->ECMpids[i].ECM_PID, pids + offs);
				i2b_buf(2, demux->ECMpids[i].CAID, pids + (offs += 2));
				i2b_buf(4, demux->ECMpids[i].PROVID, pids + (offs += 2));
				offs += 4;
			}
			snprintf((char *)lenhdr, sizeof(lenhdr), "\r\nContent-Length: %d", pids_len);
		}
		else { return -1; }
	}

	if(!context->host_id) { context->host_id = (uchar *)cs_strdup(client->reader->device); }

	encauth = _ghttp_basic_auth(client);

	if(encauth)    // basic auth login
	{
		ret = snprintf((char *)req, sizeof(req), "%s /api/p/%x/%x/%x/%x/%x HTTP/1.1\r\nHost: %s\r\nAuthorization: Basic %s%s\r\n\r\n", ((pids_len > 0) ? "POST" : "GET"), demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace, context->host_id, encauth, lenhdr);
		free(encauth);
	}
	else
	{
		if(context->session_id)    // session exists
		{
			ret = snprintf((char *)req, sizeof(req), "%s /api/p/%s/%x/%x/%x/%x/%x HTTP/1.1\r\nHost: %s%s\r\n\r\n", ((pids_len > 0) ? "POST" : "GET"), context->session_id, demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace, context->host_id, lenhdr);
		}
		else     // no credentials configured, assume no session required
		{
			ret = snprintf((char *)req, sizeof(req), "%s /api/p/%x/%x/%x/%x/%x HTTP/1.1\r\nHost: %s%s\r\n\r\n", ((pids_len > 0) ? "POST" : "GET"), demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace, context->host_id, lenhdr);
		}
	}
	end = req + ret;
	if(pids_len > 0)
	{
		memcpy(end, pids, pids_len);
		cs_debug_mask(D_CLIENT, "%s: new unscrambling detected, switching to post", client->reader->label);
		_set_pid_status(context->post_contexts, demux->onid, demux->tsid, demux->program_number, 0);
	}
	cs_ddump_mask(D_CLIENT, pids, pids_len, "%s: sending capmt ecm pids - %s /api/p/%x/%x/%x/%x/%x", client->reader->label, (pids_len > 0) ? "POST" : "GET", demux->onid, demux->tsid, demux->program_number, demux->ECMpidcount, demux->enigma_namespace);

	ret = ghttp_send(client, req, ret + pids_len);

	if(pids_len > 0) { free(pids); }

	return 0;
}
示例#6
0
int32_t ICC_Async_Transmit (struct s_reader *reader, uint32_t size, BYTE * data)
{
	cs_ddump_mask(D_IFD, data, size, "IFD Transmit: ");
	BYTE *buffer = NULL, *sent;

	if (reader->crdr.active==1) {
		if (reader->convention == ATR_CONVENTION_INVERSE && reader->crdr.need_inverse==1) {
			buffer = (BYTE *) calloc(sizeof (BYTE), size);
			memcpy (buffer, data, size);
			ICC_Async_InvertBuffer (size, buffer);
			sent = buffer;
		} else
			sent = data;

		call(reader->crdr.transmit(reader, sent, size));
		if (buffer)
			free (buffer);
		cs_debug_mask(D_IFD, "IFD Transmit succesful");
		return OK;
	}

	if (reader->convention == ATR_CONVENTION_INVERSE && reader->typ <= R_MOUSE) {
		buffer = (BYTE *) calloc(sizeof (BYTE), size);
		memcpy (buffer, data, size);
		ICC_Async_InvertBuffer (size, buffer);
		sent = buffer;
	}
	else
		sent = data;

	switch(reader->typ) {
		case R_MP35:
		case R_DB2COM1:
		case R_DB2COM2:
		case R_SC8in1:
		case R_MOUSE:
			call (Phoenix_Transmit (reader, sent, size, reader->block_delay, reader->char_delay));
			break;
#if defined(LIBUSB)
		case R_SMART:
			call (SR_Transmit(reader, sent, size));
			break;
#endif
		case R_INTERNAL:
#if defined(COOL) || defined(SU980)
			call (Cool_Transmit(reader, sent, size));
#elif defined(AZBOX)
			call (Azbox_Transmit(reader, sent, size));
#elif defined(SCI_DEV)
			call (Phoenix_Transmit (reader, sent, size, 0, 0)); //the internal reader will provide the delay
#elif defined(WITH_STAPI)
			call (STReader_Transmit(reader->stsmart_handle, sent, size));
#endif
			break;
		default:
			cs_log("ERROR ICC_Async_Transmit: unknow reader type %i",reader->typ);
			return ERROR;
	}

	if (buffer)
		free (buffer);
	cs_debug_mask(D_IFD, "IFD Transmit succesful");
	return OK;
}
示例#7
0
void cs_reinit_clients(struct s_auth *new_accounts)
{
	struct s_auth *account;
	unsigned char md5tmp[MD5_DIGEST_LENGTH];

	struct s_client *cl;
	for(cl = first_client->next; cl; cl = cl->next)
	{
		if((cl->typ == 'c' || cl->typ == 'm') && cl->account)
		{
			for(account = new_accounts; (account) ; account = account->next)
			{
				if(!strcmp(cl->account->usr, account->usr))
					{ break; }
			}
			if(account && !account->disabled && cl->pcrc == crc32(0L, MD5((uchar *)ESTR(account->pwd), strlen(ESTR(account->pwd)), md5tmp), MD5_DIGEST_LENGTH))
			{
				cl->account = account;
				if(cl->typ == 'c')
				{
					cl->grp = account->grp;
					cl->aureader_list   = account->aureader_list;
					cl->autoau = account->autoau;
					cl->expirationdate = account->expirationdate;
					cl->allowedtimeframe[0] = account->allowedtimeframe[0];
					cl->allowedtimeframe[1] = account->allowedtimeframe[1];
					cl->ncd_keepalive = account->ncd_keepalive;
					cl->c35_suppresscmd08 = account->c35_suppresscmd08;
					cl->tosleep = (60 * account->tosleep);
					cl->c35_sleepsend = account->c35_sleepsend;
					cl->monlvl = account->monlvl;
					cl->disabled    = account->disabled;
					cl->fchid   = account->fchid;  // CHID filters
					cl->cltab   = account->cltab;  // Class
					// newcamd module doesn't like ident reloading
					if(!cl->ncd_server)
						{ cl->ftab = account->ftab; }   // Ident

					cl->sidtabs.ok = account->sidtabs.ok;   // services
					cl->sidtabs.no = account->sidtabs.no;   // services
					cl->failban = account->failban;

					memcpy(&cl->ctab, &account->ctab, sizeof(cl->ctab));
					memcpy(&cl->ttab, &account->ttab, sizeof(cl->ttab));

					webif_client_reset_lastresponsetime(cl);
					if(account->uniq)
						{ cs_fake_client(cl, account->usr, (account->uniq == 1 || account->uniq == 2) ? account->uniq + 2 : account->uniq, cl->ip); }
					ac_init_client(cl, account);
				}
			}
			else
			{
				if(get_module(cl)->type & MOD_CONN_NET)
				{
					cs_debug_mask(D_TRACE, "client '%s', thread=%8lX not found in db (or password changed)", cl->account->usr, (unsigned long)cl->thread);
					kill_thread(cl);
				}
				else
				{
					cl->account = first_client->account;
				}
			}
		}
		else
		{
			cl->account = NULL;
		}
	}
}
示例#8
0
void azbox_send_dcw(struct s_client *client, ECM_REQUEST *er) {
	cs_debug_mask(D_DVBAPI, LOG_PREFIX "send_dcw");

	FILE *ecmtxt;
	if ((ecmtxt = fopen(ECMINFO_FILE, "w"))) {
		char tmp[25];
		if(er->rc <= E_CACHEEX) {
			fprintf(ecmtxt, "caid: 0x%04X\npid: 0x%04X\nprov: 0x%06X\n", er->caid, er->pid, (uint) er->prid);
			fprintf(ecmtxt, "reader: %s\n", er->selected_reader->label);
			if (is_cascading_reader(er->selected_reader))
				fprintf(ecmtxt, "from: %s\n", er->selected_reader->device);
			else
				fprintf(ecmtxt, "from: local\n");
			fprintf(ecmtxt, "protocol: %s\n", reader_get_type_desc(er->selected_reader, 1));
			fprintf(ecmtxt, "hops: %d\n", er->selected_reader->currenthops);
			fprintf(ecmtxt, "ecm time: %.3f\n", (float) client->cwlastresptime/1000);
			fprintf(ecmtxt, "cw0: %s\n", cs_hexdump(1,demux[0].lastcw[0],8, tmp, sizeof(tmp)));
			fprintf(ecmtxt, "cw1: %s\n", cs_hexdump(1,demux[0].lastcw[1],8, tmp, sizeof(tmp)));
			fclose(ecmtxt);
			ecmtxt = NULL;
		} else {
			fprintf(ecmtxt, "ECM information not found\n");
			fclose(ecmtxt);
		}
	}

	openxcas_busy = 0;

	int32_t i;
	for (i=0; i < MAX_DEMUX; i++) {
		if (er->rc >= E_NOTFOUND) {
			cs_debug_mask(D_DVBAPI, "cw not found");

			if (demux[i].pidindex==-1)
			  dvbapi_try_next_caid(i);

			openxcas_stop_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
			openxcas_remove_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);

			unsigned char mask[12];
			unsigned char comp[12];
			memset(&mask, 0x00, sizeof(mask));
			memset(&comp, 0x00, sizeof(comp));

			mask[0] = 0xfe;
			comp[0] = 0x80;

			if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, 0, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0) {
				cs_log(LOG_PREFIX "unable to add ecm filter (0)");
				if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, openxcas_caid, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0)
					cs_log(LOG_PREFIX "unable to add ecm filter (%04x)", openxcas_caid);
				else
					cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, openxcas_caid);
			} else
				cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, 0);

			if (openxcas_start_filter(openxcas_stream_id, openxcas_seq, OPENXCAS_FILTER_ECM) < 0)
				cs_log(LOG_PREFIX "unable to start ecm filter");
			else
				cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter started");

			return;
		}
	}

	unsigned char nullcw[8];
	memset(nullcw, 0, 8);

	int32_t n;
	for (n=0;n<2;n++) {
		if (memcmp(er->cw + (n * 8), demux[0].lastcw[n], 8) && memcmp(er->cw + (n * 8), nullcw, 8)) {
			memcpy(demux[0].lastcw[n], er->cw + (n * 8), 8);
			memcpy(openxcas_cw + (n * 8), er->cw + (n * 8), 8);
		}
	}

	if (openxcas_set_key(openxcas_stream_id, openxcas_seq, 0, openxcas_cipher_idx, openxcas_cw, openxcas_cw + 8) != 1)
		cs_log(LOG_PREFIX "set cw failed");
	else
		cs_ddump_mask(D_DVBAPI, openxcas_cw, 16, LOG_PREFIX "write cws to descrambler");
}
示例#9
0
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
		{
示例#10
0
int32_t MP35_Init(struct s_reader * reader)
{
  MP35_info reader_info;
  BYTE rec_buf[32];
  BYTE parameter;
  int32_t original_mhz;

  cs_debug_mask (D_IFD, "IFD: Initializing MP35 reader %s",  reader->label);

  current_product = 0;
  original_mhz = reader->mhz; // MP3.5 commands should be always be written using 9600 baud at 3.58MHz
  reader->mhz = 357;
  
  call(IO_Serial_SetParams(reader, 9600, 8, PARITY_NONE, 1, IO_SERIAL_HIGH, IO_SERIAL_HIGH));

  IO_Serial_Sendbreak(reader, MP35_BREAK_LENGTH);
  IO_Serial_DTR_Clr(reader);
  IO_Serial_DTR_Set(reader);
  cs_sleepms(200);
  IO_Serial_Flush(reader);

  memset(rec_buf, 0x00, sizeof(rec_buf));
  call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, fw_version));
  call(IO_Serial_Read(reader, MP35_READ_DELAY, 4, rec_buf));
  if(rec_buf[3] != ACK)
  {
    cs_debug_mask (D_IFD, "IFD: Failed MP35 command: fw_version");
    return ERROR;
  }

  if(MP35_product_info(rec_buf[1], rec_buf[0], rec_buf[2], &reader_info) != OK)
  {
    cs_log("MP35_Init: unknown product code");
    return ERROR;
  }

  if(reader_info.current_product == 0x10) // USB Phoenix
  {
    if(original_mhz == 357)
    {
      cs_log("MP35_Init: Using oscillator 1 (3.57MHz)");
      parameter = 0x01;
    }
    else if(original_mhz == 368)
    {
      cs_log("MP35_Init: Using oscillator 2 (3.68MHz)");
      parameter = 0x02;
    }
    else if(original_mhz == 600)
    {
      cs_log("MP35_Init: Using oscillator 3 (6.00MHz)");
      parameter = 0x03;
    }
    else
    {
      cs_log("MP35_Init: MP35 support only mhz=357, mhz=368 or mhz=600");
      cs_log("MP35_Init: Forced oscillator 1 (3.57MHz)");
      parameter = 0x01;
      original_mhz = 357;
    }
    memset(rec_buf, 0x00, sizeof(rec_buf));
    call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, set_mode_osc));
    call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1, &parameter));
    call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf)); // Read ACK from previous command
    if(rec_buf[0] != ACK)
    {
      cs_debug_mask (D_IFD, "IFD: Failed MP35 command: set_mode_osc");
      return ERROR;
    }
    cs_log("MP35_Init: Leaving programming mode");
    memset(rec_buf, 0x00, sizeof(rec_buf));
    call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, exit_program_mode));
    call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf));
    if(rec_buf[0] != ACK)
    {
      cs_debug_mask (D_IFD, "IFD: Failed MP35 command: exit_program_mode");
      return ERROR;
    }
  }
  else //MP3.5 or MP3.6
  {
    if(reader_info.product_fw_version >= 0x0500)
    {
      int32_t info_len;
      char info[sizeof(rec_buf) - 2];

      memset(rec_buf, 0x00, sizeof(rec_buf));
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2,  fw_info));
      call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf));
      info_len = rec_buf[0];
      call(IO_Serial_Read(reader, MP35_READ_DELAY, info_len + 1, rec_buf));
      if(rec_buf[info_len] != ACK)
      {
        cs_debug_mask (D_IFD, "IFD: Failed MP35 command: fw_info");
        return ERROR;
      }
      memcpy(info, rec_buf, info_len);
      info[info_len] = '\0';
      cs_log("MP35_Init: FW Info - %s", info);
    }

    memset(rec_buf, 0x00, sizeof(rec_buf));
    if(original_mhz == 357)
    {
      cs_log("MP35_Init: Using oscillator 1 (3.57MHz)");
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode));
    }
    else if(original_mhz == 600)
    {
      cs_log("MP35_Init: Using oscillator 2 (6.00MHz)");
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_6mhz_mode));
    }
    else
    {
      cs_log("MP35_Init: MP35 support only mhz=357 or mhz=600");
      cs_log("MP35_Init: Forced oscillator 1 (3.57MHz)");
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode));
      original_mhz = 357;
    }
  }

  reader->mhz = original_mhz; // We might have switched oscillator here
  current_product = reader_info.current_product;
  IO_Serial_Flush(reader);

  return OK;
}
示例#11
0
文件: reader-dre.c 项目: rosner/oscam
static int32_t dre_command (struct s_reader * reader, const uchar * cmd, int32_t cmdlen, unsigned char * cta_res, uint16_t * p_cta_lr)	//attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
{
    uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 };	//any command starts with this,
    //last byte is nr of bytes of the command that will be sent
    //after the startcmd
//response on startcmd+cmd:     = { 0x61, 0x05 }  //0x61 = "OK", last byte is nr. of bytes card will send
    uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 };	//after command answer has to be requested,
    //last byte must be nr. of bytes that card has reported to send
    uchar command[256];
    char tmp[256];
    int32_t headerlen = sizeof (startcmd);
    startcmd[4] = cmdlen + 3;	//commandlength + type + len + checksum bytes
    memcpy (command, startcmd, headerlen);
    command[headerlen++] = CMD_BYTE;	//type
    command[headerlen++] = cmdlen + 1;	//len = command + 1 checksum byte
    memcpy (command + headerlen, cmd, cmdlen);

    uchar checksum = ~xor (cmd, cmdlen);
    //cs_debug_mask(D_READER, "[dre-reader] Checksum: %02x", checksum);
    cmdlen += headerlen;
    command[cmdlen++] = checksum;

    reader_cmd2icc (reader, command, cmdlen, cta_res, p_cta_lr);

    if ((*p_cta_lr != 2) || (cta_res[0] != OK_RESPONSE)) {
        cs_log ("[dre-reader] command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
        cs_log ("[dre-reader] unexpected answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
        return ERROR;			//error
    }

    reqans[4] = cta_res[1];	//adapt length byte
    reader_cmd2icc (reader, reqans, 5, cta_res, p_cta_lr);

    if (cta_res[0] != CMD_BYTE) {
        cs_log ("[dre-reader] unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
        return ERROR;
    }
    if ((cta_res[1] == 0x03) && (cta_res[2] == 0xe2)) {
        switch (cta_res[3]) {
        case 0xe1:
            cs_log ("[dre-reader] checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe2:
            cs_log ("[dre-reader] wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe3:
            cs_log ("[dre-reader] illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xec:
            cs_log ("[dre-reader] wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        default:
            cs_debug_mask(D_READER, "[dre-reader] unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        }
        return ERROR;			//error
    }
    int32_t length_excl_leader = *p_cta_lr;
    if ((cta_res[*p_cta_lr - 2] == 0x90) && (cta_res[*p_cta_lr - 1] == 0x00))
        length_excl_leader -= 2;

    checksum = ~xor (cta_res + 2, length_excl_leader - 3);

    if (cta_res[length_excl_leader - 1] != checksum) {
        cs_log ("[dre-reader] checksum does not match, expected %02x received %02x:%s", checksum,
                cta_res[length_excl_leader - 1], cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
        return ERROR;			//error
    }
    return OK;
}
示例#12
0
void ac_do_stat(void)
{
	int32_t j, idx, exceeds, maxval, prev_deny = 0;

	struct s_client *client;
	for(client = first_client; client; client = client->next)
	{
		if(client->typ != 'c') { continue; }

		struct s_acasc *ac_stat = &client->account->ac_stat;
		struct s_acasc_shm *acasc = &client->acasc;

		idx = ac_stat->idx;
		ac_stat->stat[idx] = acasc->ac_count;
		acasc->ac_count = 0;

		if(ac_stat->stat[idx])
		{
			if(client->ac_penalty == 2)    // banned
			{
				cs_debug_mask(D_CLIENT, "acasc: user '%s' banned", client->account->usr);
				acasc->ac_deny = 1;
			}
			else
			{
				for(j = exceeds = maxval = 0; j < cfg.ac_samples; j++)
				{
					if(ac_stat->stat[j] > maxval)
						{ maxval = ac_stat->stat[j]; }
					exceeds += (ac_stat->stat[j] > client->ac_limit);
				}
				prev_deny = acasc->ac_deny;
				acasc->ac_deny = (exceeds >= cfg.ac_denysamples);

				cs_debug_mask(D_CLIENT, "acasc: %s limit=%d, max=%d, samples=%d, dsamples=%d, [idx=%d]:",
							  client->account->usr, client->ac_limit, maxval,
							  cfg.ac_samples, cfg.ac_denysamples, idx);
				cs_debug_mask(D_CLIENT, "acasc: %d %d %d %d %d %d %d %d %d %d ", ac_stat->stat[0],
							  ac_stat->stat[1], ac_stat->stat[2], ac_stat->stat[3],
							  ac_stat->stat[4], ac_stat->stat[5], ac_stat->stat[6],
							  ac_stat->stat[7], ac_stat->stat[8], ac_stat->stat[9]);
				if(acasc->ac_deny)
				{
					cs_log("acasc: user '%s' exceeds limit", client->account->usr);
					ac_stat->stat[idx] = 0;
				}
				else if(prev_deny)
					{ cs_log("acasc: user '%s' restored access", client->account->usr); }
			}
		}
		else if(acasc->ac_deny)
		{
			prev_deny = 1;
			acasc->ac_deny = 0;
			cs_log("acasc: restored access for inactive user '%s'", client->account->usr);
		}

		if(!acasc->ac_deny && !prev_deny)
			{ ac_stat->idx = (ac_stat->idx + 1) % cfg.ac_samples; }
	}
}
示例#13
0
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;
					free(last_cpmap);
				}
				free(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_debug_mask(D_CLIENT, "nr=%d, caid=%04X, provid=%06X, sid=%04X, chid=%04X, dwtime=%d",
						  nr, caid, provid, sid, chid, dwtime);
			nr++;
		}
	}
	free(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;
}
示例#14
0
/* Checks if authentication is correct. Returns -1 if not correct, 1 if correct and 2 if nonce isn't valid anymore.
   Note that authstring will be modified. */
int32_t check_auth(char *authstring, char *method, char *path, IN_ADDR_T addr, char *expectednonce, char *opaque)
{
	int32_t authok = 0, uriok = 0;
	char authnonce[(MD5_DIGEST_LENGTH * 2) + 1];
	memset(authnonce, 0, sizeof(authnonce));
	char *authnc = "";
	char *authcnonce = "";
	char *authresponse = "";
	char *uri = "";
	char *username = "";
	char *expectedPassword = cfg.http_pwd;
	char *pch = authstring + 22;
	char *pch2;
	char *saveptr1 = NULL;
	memset(opaque, 0, (MD5_DIGEST_LENGTH * 2) + 1);

	for(pch = strtok_r(pch, ",", &saveptr1); pch; pch = strtok_r(NULL, ",", &saveptr1))
	{
		pch2 = pch;
		while(pch2[0] == ' ' && pch2[0] != '\0') { ++pch2; }
		if(strncmp(pch2, "nonce", 5) == 0)
		{
			cs_strncpy(authnonce, parse_auth_value(pch2), sizeof(authnonce));
		}
		else if(strncmp(pch2, "nc", 2) == 0)
		{
			authnc = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "cnonce", 6) == 0)
		{
			authcnonce = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "response", 8) == 0)
		{
			authresponse = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "uri", 3) == 0)
		{
			uri = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "username", 8) == 0)
		{
			username = parse_auth_value(pch2);
		}
		else if(strncmp(pch2, "opaque", 6) == 0)
		{
			char *tmp = parse_auth_value(pch2);
			cs_strncpy(opaque, tmp, (MD5_DIGEST_LENGTH * 2) + 1);
		}
	}

	if(strncmp(uri, path, strlen(path)) == 0) { uriok = 1; }
	else
	{
		pch2 = uri;
		for(pch = uri; pch[0] != '\0'; ++pch)
		{
			if(pch[0] == '/') { pch2 = pch; }
			if(strncmp(pch2, path, strlen(path)) == 0) { uriok = 1; }
		}
	}
	if(uriok == 1 && streq(username, cfg.http_user))
	{
		char A1tmp[3 + strlen(username) + strlen(AUTHREALM) + strlen(expectedPassword)];
		char A1[(MD5_DIGEST_LENGTH * 2) + 1], A2[(MD5_DIGEST_LENGTH * 2) + 1], A3[(MD5_DIGEST_LENGTH * 2) + 1];
		unsigned char md5tmp[MD5_DIGEST_LENGTH];
		snprintf(A1tmp, sizeof(A1tmp), "%s:%s:%s", username, AUTHREALM, expectedPassword);
		char_to_hex(MD5((unsigned char *)A1tmp, strlen(A1tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A1);

		char A2tmp[2 + strlen(method) + strlen(uri)];
		snprintf(A2tmp, sizeof(A2tmp), "%s:%s", method, uri);
		char_to_hex(MD5((unsigned char *)A2tmp, strlen(A2tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A2);

		char A3tmp[10 + strlen(A1) + strlen(A2) + strlen(authnonce) + strlen(authnc) + strlen(authcnonce)];
		snprintf(A3tmp, sizeof(A3tmp), "%s:%s:%s:%s:auth:%s", A1, authnonce, authnc, authcnonce, A2);
		char_to_hex(MD5((unsigned char *)A3tmp, strlen(A3tmp), md5tmp), MD5_DIGEST_LENGTH, (unsigned char *)A3);

		if(strcmp(A3, authresponse) == 0)
		{
			if(strlen(opaque) != MD5_DIGEST_LENGTH * 2) { calculate_opaque(addr, opaque); }
			calculate_nonce(authnonce, expectednonce, opaque);
			if(strcmp(expectednonce, authnonce) == 0) { authok = 1; }
			else
			{
				authok = 2;
				cs_debug_mask(D_TRACE, "WebIf: Received stale header from %s (nonce=%s, expectednonce=%s, opaque=%s).", cs_inet_ntoa(addr), authnonce, expectednonce, opaque);
			}
		}
	}
	return authok;
}
示例#15
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;
}
示例#16
0
void * azbox_main_thread(void *cli) {
	struct s_client * client = (struct s_client *) cli;
	client->thread=pthread_self();
	pthread_setspecific(getclient, cli);
	dvbapi_client=cli;

	struct s_auth *account;
	int32_t ok = 0;
	for (account = cfg.account; account; account=account->next) {
		if ((ok = streq(cfg.dvbapi_usr, account->usr)))
			break;
	}
	cs_auth_client(client, ok ? account : (struct s_auth *)(-1), "dvbapi");

	dvbapi_read_priority();

	openxcas_msg_t msg;
	int32_t ret;
	while ((ret = openxcas_get_message(&msg, 0)) >= 0) {
		cs_sleepms(10);

		if (ret) {
			openxcas_stream_id = msg.stream_id;
			openxcas_seq = msg.sequence;

			switch(msg.cmd) {
				case OPENXCAS_SELECT_CHANNEL:
					cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_SELECT_CHANNEL");

					// parse channel info
					struct stOpenXCASChannel chan;
					memcpy(&chan, msg.buf, msg.buf_len);

					cs_log(LOG_PREFIX "channel change: sid = %x, vpid = %x. apid = %x", chan.service_id, chan.v_pid, chan.a_pid);

					openxcas_video_pid = chan.v_pid;
					openxcas_audio_pid = chan.a_pid;
					openxcas_data_pid = chan.d_pid;
					break;
				case OPENXCAS_START_PMT_ECM:
					cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_START_PMT_ECM");

					 // parse pmt
					uchar *dest;
					if (!cs_malloc(&dest, msg.buf_len + 7 - 12 - 4))
						break;

					memcpy(dest, "\x00\xFF\xFF\x00\x00\x13\x00", 7);

					dest[1] = msg.buf[3];
					dest[2] = msg.buf[4];
					dest[5] = msg.buf[11]+1;

					memcpy(dest + 7, msg.buf + 12, msg.buf_len - 12 - 4);

					dvbapi_parse_capmt(dest, 7 + msg.buf_len - 12 - 4, -1, NULL);
					free(dest);

					unsigned char mask[12];
					unsigned char comp[12];
					memset(&mask, 0x00, sizeof(mask));
					memset(&comp, 0x00, sizeof(comp));

					mask[0] = 0xfe;
					comp[0] = 0x80;

					if ((ret = openxcas_add_filter(msg.stream_id, OPENXCAS_FILTER_ECM, 0, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback)) < 0)
						cs_log(LOG_PREFIX "unable to add ecm filter");
					else
						cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, 0);

					if (openxcas_start_filter(msg.stream_id, msg.sequence, OPENXCAS_FILTER_ECM) < 0)
						cs_log(LOG_PREFIX "unable to start ecm filter");
					else
						cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter started");

					if (!openxcas_create_cipher_ex(msg.stream_id, openxcas_seq, 0, openxcas_ecm_pid, openxcas_video_pid, 0xffff, openxcas_audio_pid, 0xffff, 0xffff, 0xffff))
						cs_log(LOG_PREFIX "failed to create cipher ex");
					else
						cs_debug_mask(D_DVBAPI, LOG_PREFIX "cipher created");
					break;
				case OPENXCAS_STOP_PMT_ECM:
					cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_STOP_PMT_ECM");
					openxcas_stop_filter(msg.stream_id, OPENXCAS_FILTER_ECM);
					openxcas_remove_filter(msg.stream_id, OPENXCAS_FILTER_ECM);
					openxcas_stop_filter_ex(msg.stream_id, msg.sequence, openxcas_filter_idx);
					openxcas_destory_cipher_ex(msg.stream_id, msg.sequence);
					memset(&demux, 0, sizeof(demux));
					break;
				case OPENXCAS_ECM_CALLBACK:
					cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_ECM_CALLBACK");
					struct stOpenXCAS_Data data;
					memcpy(&data, msg.buf, msg.buf_len);
					if (!openxcas_busy)
					  openxcas_filter_callback(msg.stream_id, msg.sequence, OPENXCAS_FILTER_ECM, &data);
					break;
				case OPENXCAS_PID_FILTER_CALLBACK:
					cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_PID_FILTER_CALLBACK");
					openxcas_filter_callback_ex(msg.stream_id, msg.sequence, (struct stOpenXCAS_Data *)msg.buf);
					break;
				case OPENXCAS_QUIT:
					cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_QUIT");
					openxcas_close();
					cs_log(LOG_PREFIX "exited");
					return NULL;
					break;
				case OPENXCAS_UKNOWN_MSG:
				default:
					cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_UKNOWN_MSG (%d)", msg.cmd);
					//cs_ddump_mask(D_DVBAPI, &msg, sizeof(msg), "msg dump:");
					break;
			}
		}
	}
	cs_log(LOG_PREFIX "invalid message");
	return NULL;
}
示例#17
0
static int32_t viaccess_do_ecm(struct s_reader * reader, ECM_REQUEST *er)
{
	def_resp;
	static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
	unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
	unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
	static const unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw

	uchar *ecm88Data=er->ecm+4; //XXX what is the 4th byte for ??
	int32_t ecm88Len=SCT_LEN(er->ecm)-4;
	uint32_t provid=0;
	int32_t rc=0;
	int32_t hasD2 = 0;
	int32_t curEcm88len=0;
	int32_t nanoLen=0;
	uchar *nextEcm;
	uchar DE04[256];
	int32_t D2KeyID=0;
	int32_t curnumber_ecm=0;
	//nanoD2 d2 02 0d 02 -> D2 nano, len 2
	// 0d -> post AES decrypt CW
	// 0b -> pre AES decrypt CW
	int32_t nanoD2 = 0; //   0x0b = 1  0x0d = 2

	memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug

	nextEcm=ecm88Data;

	
	while (ecm88Len && !rc) {

		if(ecm88Data[0] ==0x00 &&  ecm88Data[1] == 0x00) {
			// nano 0x00  and len 0x00 aren't valid ... something is obviously wrong with this ecm.
			cs_log("[viaccess-reader] ECM: Invalid ECM structure. Rejecting");
			return ERROR;
		}

		// 80 33 nano 80 (ecm) + len (33)
		if(ecm88Data[0]==0x80) { // nano 80, give ecm len
			curEcm88len=ecm88Data[1];
			nextEcm=ecm88Data+curEcm88len+2;
			ecm88Data += 2;
			ecm88Len -= 2;
		}

		if(!curEcm88len) { //there was no nano 80 -> simple ecm
			curEcm88len=ecm88Len;
		}

		// d2 02 0d 02 -> D2 nano, len 2,  select the AES key to be used
		if(ecm88Data[0]==0xd2) {
			// test if need post or pre AES decrypt
			if(ecm88Data[2]==0x0b)
			{
				nanoD2 = 1;
				cs_debug_mask(D_READER, "[viaccess-reader] ECM: nano D2 0x0b");
			}
			if(ecm88Data[2]==0x0d)
			{
				nanoD2 = 2;
				cs_debug_mask(D_READER, "[viaccess-reader] ECM: nano D2 0x0d");
			}
			// use the d2 arguments to get the key # to be used
			int32_t len = ecm88Data[1] + 2;
			D2KeyID=ecm88Data[3];
			ecm88Data += len;
			ecm88Len -= len;
			curEcm88len -=len;
			hasD2 = 1;
		}
		else
			hasD2 = 0;


		// 40 07 03 0b 00  -> nano 40, len =7  ident 030B00 (tntsat), key #0  <== we're pointing here
		// 09 -> use key #9
		// 05 67 00
		if ((ecm88Data[0]==0x90 || ecm88Data[0]==0x40) && (ecm88Data[1]==0x03 || ecm88Data[1]==0x07 ) )
		{
			uchar ident[3], keynr;
			uchar *ecmf8Data=0;
			int32_t ecmf8Len=0;

			nanoLen=ecm88Data[1] + 2;
			keynr=ecm88Data[4]&0x0F;

			// 40 07 03 0b 00  -> nano 40, len =7  ident 030B00 (tntsat), key #0  <== we're pointing here
			// 09 -> use key #9
			if(nanoLen>5) {
				curnumber_ecm =(ecm88Data[6]<<8) | (ecm88Data[7]);
				cs_debug_mask(D_READER, "checking if the ecm number (%x) match the card one (%x)",curnumber_ecm,reader->last_geo.number_ecm);
				// if we have an ecm number we check it.
				// we can't assume that if the nano len is 5 or more we have an ecm number
				// as some card don't support this
				//force use ecm 00 provider 030B00 & 032920 & 032940
				if( reader->last_geo.number_ecm > 0 )
				{
					if(ecm88Data[2] == 0x03 && ((ecm88Data[3] == 0x0B && ecm88Data[4] == 0x00)||
						                        (ecm88Data[3] == 0x29 && ecm88Data[4] == 0x20)||
												(ecm88Data[3] == 0x29 && ecm88Data[4] == 0x40)))
					{
						if (reader->last_geo.number_ecm == curnumber_ecm && !( ecm88Data[nanoLen-1] == 0x01 )) //ecm 00
						{
							keynr=ecm88Data[5];
							cs_debug_mask(D_READER, "keyToUse = %02x, ECM ending with %02x",ecm88Data[5], ecm88Data[nanoLen-1]);
						}
						else
						{
							// ecm 01
							if( ecm88Data[nanoLen-1] == 0x01 )
							{
								cs_debug_mask(D_READER, "Skip ECM ending with = %02x for ecm number (%x) for provider %02x%02x%02x",ecm88Data[nanoLen-1], curnumber_ecm, ecm88Data[2], ecm88Data[3], ecm88Data[4]);
							}
							cs_debug_mask(D_READER, "Skip ECM ending with = %02x for ecm number (%x)",ecm88Data[nanoLen-1], curnumber_ecm);
							ecm88Data=nextEcm;
							ecm88Len-=curEcm88len;
							continue; //loop to next ecm
						}
					}
				}
				else { // long ecm but we don't have an ecm number so we have to try them all.
					keynr=ecm88Data[5];
					cs_debug_mask(D_READER, "keyToUse = %02x",ecm88Data[5]);
				}
			}

			memcpy (ident, &ecm88Data[2], sizeof(ident));
			provid = b2i(3, ident);
			ident[2]&=0xF0;

			if(hasD2 && reader->aes_list) {
				// check that we have the AES key to decode the CW
				// if not there is no need to send the ecm to the card
				if(!aes_present(reader->aes_list, 0x500, (uint32_t) (provid & 0xFFFFF0) , D2KeyID))
					return ERROR;
			}


			if (!chk_prov(reader, ident, keynr))
			{
				cs_debug_mask(D_READER, "[viaccess-reader] ECM: provider or key not found on card");
				snprintf( er->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0],ident[1],ident[2], keynr );
				return ERROR;
			}

			ecm88Data+=nanoLen;
			ecm88Len-=nanoLen;
			curEcm88len-=nanoLen;

			// DE04
			if (ecm88Data[0]==0xDE && ecm88Data[1]==0x04)
			{
				memcpy (DE04, &ecm88Data[0], 6);
				ecm88Data+=6;
			}
			//

			if( reader->last_geo.provid != provid )
			{
				reader->last_geo.provid = provid;
				reader->last_geo.geo_len = 0;
				reader->last_geo.geo[0]  = 0;
				write_cmd(insa4, ident); // set provider
			}

			//Nano D2 0x0b Pre AES decrypt CW
			if ( hasD2 && nanoD2 == 1)
			{
				uchar *ecm88DataCW = ecm88Data;
				int32_t cwStart = 0;
				//int32_t cwStartRes = 0;
				int32_t exit = 0;
				// find CW start
				while(cwStart < curEcm88len -1 && !exit)
				{
					if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart+1] == 0x10)
					{
						ecm88DataCW = ecm88DataCW + cwStart + 2;
						exit = 1;
					}
					cwStart++;
				}
				// use AES from list to decrypt CW
				cs_debug_mask(D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
				if (aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16) == 0)
					snprintf( er->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
			}

			while(ecm88Len>0 && ecm88Data[0]<0xA0)
			{
				int32_t nanoLen=ecm88Data[1]+2;
				if (!ecmf8Data)
					ecmf8Data=(uchar *)ecm88Data;
				ecmf8Len+=nanoLen;
				ecm88Len-=nanoLen;
				curEcm88len-=nanoLen;
				ecm88Data+=nanoLen;
			}
			if(ecmf8Len)
			{
				if( reader->last_geo.geo_len!=ecmf8Len ||
					memcmp(reader->last_geo.geo, ecmf8Data, reader->last_geo.geo_len))
				{
					memcpy(reader->last_geo.geo, ecmf8Data, ecmf8Len);
					reader->last_geo.geo_len= ecmf8Len;
					insf8[3]=keynr;
					insf8[4]=ecmf8Len;
					write_cmd(insf8, ecmf8Data);
				}
			}
			ins88[2]=ecmf8Len?1:0;
			ins88[3]=keynr;
			ins88[4]= curEcm88len;
			//
			// we should check the nano to make sure the ecm is valid
			// we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
			//
			// DE04
			if (DE04[0]==0xDE)
			{
				memcpy(DE04+6, (uchar *)ecm88Data, curEcm88len-6);
				write_cmd(ins88, DE04); // request dcw
			}
			else
			{
				write_cmd(ins88, (uchar *)ecm88Data); // request dcw
			}
			//
			write_cmd(insc0, NULL);	// read dcw
			switch(cta_res[0])
			{
			case 0xe8: // even
				if(cta_res[1]==8) { memcpy(er->cw,cta_res+2,8); rc=1; }
				break;
			case 0xe9: // odd
				if(cta_res[1]==8) { memcpy(er->cw+8,cta_res+2,8); rc=1; }
				break;
			case 0xea: // complete
				if(cta_res[1]==16) { memcpy(er->cw,cta_res+2,16); rc=1; }
				break;
			default :
				ecm88Data=nextEcm;
				ecm88Len-=curEcm88len;
				cs_debug_mask(D_READER, "[viaccess-reader] ECM: key to use is not the current one, trying next ECM");
				snprintf( er->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM" );
			}
		}
		else {
			ecm88Data=nextEcm;
			ecm88Len-=curEcm88len;
			cs_debug_mask(D_READER, "[viaccess-reader] ECM: Unknown ECM type");
			snprintf( er->msglog, MSGLOGSIZE, "Unknown ECM type" );
		}
	}

	if ( hasD2 && !dcw_crc(er->cw) && nanoD2 == 2) {
		cs_debug_mask(D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
		rc=aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID,er->cw, 16);
		if( rc == 0 )
			snprintf( er->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
	}

	return(rc?OK:ERROR);
}
示例#18
0
static int32_t ghttp_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t n)
{
	char *data;
	char *hdrstr;
	uchar *content;
	int rcode, len, clen = 0;
	s_ghttp *context = (s_ghttp *)client->ghttp;
	ECM_REQUEST *er = NULL;

	if(n < 5) { return -1; }

	data = strstr((char *)buf, "HTTP/1.1 ");
	if(!data || ll_count(context->ecm_q) > 6)
	{
		cs_debug_mask(D_CLIENT, "%s: non http or otherwise corrupt response: %s", client->reader->label, buf);
		cs_ddump_mask(D_CLIENT, buf, n, "%s: ", client->reader->label);
		network_tcp_connection_close(client->reader, "receive error");
		NULLFREE(context->session_id);
		ll_clear(context->ecm_q);
		return -1;
	}

	LL_ITER itr = ll_iter_create(context->ecm_q);
	er = (ECM_REQUEST *)ll_iter_next(&itr);

	rcode = _get_int_header(buf, "HTTP/1.1 ");
	clen = _get_int_header(buf, "Content-Length: ");

	content = (uchar *)(strstr(data, "\r\n\r\n") + 4);

	hdrstr = _get_header_substr(buf, "ETag: \"", "\"\r\n");
	if(hdrstr)
	{
		NULLFREE(context->host_id);
		context->host_id = (uchar *)hdrstr;
		cs_debug_mask(D_CLIENT, "%s: new name: %s", client->reader->label, context->host_id);
		len = b64decode(context->host_id);
		if(len == 0 || len >= 64)
		{
			NULLFREE(context->host_id);
		}
		else
		{
			cs_debug_mask(D_CLIENT, "%s: redirected...", client->reader->label);
			NULLFREE(context->session_id);
			ll_clear_data(ghttp_ignored_contexts);
			ll_clear(context->ecm_q);
			return -1;
		}
	}

	hdrstr = _get_header_substr(buf, "ETag: W/\"", "\"\r\n");
	if(hdrstr)
	{
		NULLFREE(context->fallback_id);
		context->fallback_id = (uchar *)hdrstr;
		cs_debug_mask(D_CLIENT, "%s: new fallback name: %s", client->reader->label, context->fallback_id);
		len = b64decode(context->fallback_id);
		if(len == 0 || len >= 64)
		{
			NULLFREE(context->fallback_id);
		}
	}

	hdrstr = _get_header(buf, "Set-Cookie: GSSID=");
	if(hdrstr)
	{
		NULLFREE(context->session_id);
		context->session_id = (uchar *)hdrstr;
		cs_debug_mask(D_CLIENT, "%s: set session_id to: %s", client->reader->label, context->session_id);
	}

	// buf[n] = '\0';
	// cs_ddump_mask(D_TRACE, content, clen, "%s: reply\n%s", client->reader->label, buf);

	if(rcode < 200 || rcode > 204)
	{
		cs_debug_mask(D_CLIENT, "%s: http error code %d", client->reader->label, rcode);
		data = strstr((char *)buf, "Content-Type: application/octet-stream"); // if not octet-stream, google error. need reconnect?
		if(data)    // we have error info string in the post content
		{
			if(clen > 0)
			{
				content[clen] = '\0';
				cs_debug_mask(D_CLIENT, "%s: http error message: %s", client->reader->label, content);
			}
		}
		if(rcode == 503)
		{
			if(er && _is_post_context(context->post_contexts, er, false))
			{
				if(_swap_hosts(context))
				{
					cs_debug_mask(D_CLIENT, "%s: switching to fallback", client->reader->label);
				}
				else
				{
					cs_debug_mask(D_CLIENT, "%s: recv_chk got 503 despite post, trying reconnect", client->reader->label);
					network_tcp_connection_close(client->reader, "reconnect");
					ll_clear(context->ecm_q);
				}
			}
			else
			{
				// on 503 cache timeout, retry with POST immediately (and switch to POST for subsequent)
				if(er)
				{
					_set_pid_status(context->post_contexts, er->onid, er->tsid, er->srvid, 0);
					cs_debug_mask(D_CLIENT, "%s: recv_chk got 503, trying direct post", client->reader->label);
					_ghttp_post_ecmdata(client, er);
				}
			}
		}
		else if(rcode == 401)
		{
			NULLFREE(context->session_id);
			if(er)
			{
				cs_debug_mask(D_CLIENT, "%s: session expired, trying direct post", client->reader->label);
				_ghttp_post_ecmdata(client, er);
			}
		}
		else if(rcode == 403)
		{
			client->reader->enable = 0;
			network_tcp_connection_close(client->reader, "login failure");
			ll_clear(context->ecm_q);
			cs_log("%s: invalid username/password, disabling reader.", client->reader->label);
		}

		// not sure if this is needed on failure, copied from newcamd
		*rc = 0;
		memset(dcw, 0, 16);

		return -1;
	}

	// successful http reply (200 ok or 204 no content)

	hdrstr = _get_header(buf,  "Pragma: context-ignore=");
	if(hdrstr)
	{
		if(clen > 1)
		{
			cs_ddump_mask(D_CLIENT, content, clen, "%s: pmt ignore reply - %s (%d pids)", client->reader->label, hdrstr, clen / 2);
			uint32_t onid = 0, tsid = 0, sid = 0;
			if(sscanf(hdrstr, "%4x-%4x-%4x", &onid, &tsid, &sid) == 3)
				{ _set_pids_status(ghttp_ignored_contexts, onid, tsid, sid, content, clen); }
			NULLFREE(hdrstr);
			return -1;
		}
		NULLFREE(hdrstr);
	}

	data = strstr((char *)buf, "Pragma: context-ignore-clear");
	if(data)
	{
		cs_debug_mask(D_CLIENT, "%s: clearing local ignore list (size %d)", client->reader->label, ll_count(ghttp_ignored_contexts));
		ll_clear_data(ghttp_ignored_contexts);
	}

	// switch back to cache get after rapid ecm response (arbitrary atm), only effect is a slight bw save for client
	if(!er || _is_post_context(context->post_contexts, er, false))
	{
		data = strstr((char *)buf, "Pragma: cached");
		if(data || (client->cwlastresptime > 0 && client->cwlastresptime < 640))
		{
			cs_debug_mask(D_CLIENT, "%s: probably cached cw (%d ms), switching back to cache get for next req", client->reader->label, client->cwlastresptime);
			if(er) { _is_post_context(context->post_contexts, er, true); }
		}
	}

	if(clen == 16)    // cw in content
	{
		memcpy(dcw, content, 16);
		*rc = 1;
		er = ll_remove_first(context->ecm_q);
		if(!er) { return -1; }
		cs_ddump_mask(D_TRACE, dcw, 16, "%s: cw recv chk for idx %d", client->reader->label, er->idx);
		return er->idx;
	}
	else
	{
		if(clen != 0) { cs_ddump_mask(D_CLIENT, content, clen, "%s: recv_chk fail, clen = %d", client->reader->label, clen); }
	}
	return -1;
}
示例#19
0
static int32_t viaccess_do_emm(struct s_reader * reader, EMM_PACKET *ep)
{
	def_resp;
	static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
	unsigned char insf0[] = { 0xca,0xf0,0x00,0x01,0x22 }; // set adf
	unsigned char insf4[] = { 0xca,0xf4,0x00,0x01,0x00 }; // set adf, encrypted
	unsigned char ins18[] = { 0xca,0x18,0x01,0x01,0x00 }; // set subscription
	unsigned char ins1c[] = { 0xca,0x1c,0x01,0x01,0x00 }; // set subscription, encrypted
	static const unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
	// static const unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status

	int32_t emmdatastart=7;


	if (ep->type == UNIQUE) emmdatastart++;
	int32_t emmLen=SCT_LEN(ep->emm)-emmdatastart;
	int32_t rc=0;

	///cs_dump(ep->emm, emmLen+emmdatastart, "RECEIVED EMM VIACCESS");

	int32_t emmUpToEnd;
	uchar *emmParsed = ep->emm+emmdatastart;
	int32_t provider_ok = 0;
	uint32_t emm_provid;
	uchar keynr = 0;
	int32_t ins18Len = 0;
	uchar ins18Data[512];
	uchar insData[512];
	uchar *nano81Data = 0;
	uchar *nano91Data = 0;
	uchar *nano92Data = 0;
	uchar *nano9EData = 0;
	uchar *nanoF0Data = 0;

	for (emmUpToEnd=emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1])) {
		///cs_dump (emmParsed, emmParsed[1] + 2, "NANO");

		if (emmParsed[0]==0x90 && emmParsed[1]==0x03) {
			/* identification of the service operator */

			uchar soid[3], ident[3], i;

			for (i=0; i<3; i++) {
				soid[i]=ident[i]=emmParsed[2+i];
			}
			ident[2]&=0xF0;
			emm_provid=b2i(3, ident);
			keynr=soid[2]&0x0F;
			if (chk_prov(reader, ident, keynr)) {
				provider_ok = 1;
			} else {
				cs_debug_mask(D_READER, "[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
				cs_log("[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
				return ERROR;
			}

			// check if the provider changes. If yes, set the new one. If not, don't .. card will return an error if we do.
			if( reader->last_geo.provid != emm_provid ) {
				write_cmd(insa4, ident);
				if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
					cs_dump(insa4, 5, "set provider cmd:");
					cs_dump(soid, 3, "set provider data:");
					cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
					return ERROR;
				}
			}
			// as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
			reader->last_geo.provid = 0;
			reader->last_geo.geo_len = 0;
			reader->last_geo.geo[0]  = 0;

		}
		else if (emmParsed[0]==0x9e && emmParsed[1]==0x20) {
			/* adf */

			if (!nano91Data) {
				/* adf is not crypted, so test it */

				uchar custwp;
				uchar *afd;

				custwp=reader->sa[0][3];
				afd=(uchar*)emmParsed+2;

				if( afd[31-custwp/8] & (1 << (custwp & 7)) )
					cs_debug_mask(D_READER, "[viaccess-reader] emm for our card %08X", b2i(4, &reader->sa[0][0]));
				else
					return SKIPPED;
			}

			// memorize
			nano9EData = emmParsed;

		} else if (emmParsed[0]==0x81) {
			nano81Data = emmParsed;
		} else if (emmParsed[0]==0x91 && emmParsed[1]==0x08) {
			nano91Data = emmParsed;
		} else if (emmParsed[0]==0x92 && emmParsed[1]==0x08) {
			nano92Data = emmParsed;
		} else if (emmParsed[0]==0xF0 && emmParsed[1]==0x08) {
			nanoF0Data = emmParsed;
		} else {
			/* other nanos */
			show_subs(reader, emmParsed);

			memcpy(ins18Data+ins18Len, emmParsed, emmParsed[1] + 2);
			ins18Len += emmParsed [1] + 2;
		}
	}

	if (!provider_ok) {
		cs_debug_mask(D_READER, "[viaccess-reader] provider not found in emm, continue anyway");
		// force key to 1...
		keynr = 1;
		///return ERROR;
	}

	if (!nanoF0Data) {
		cs_dump(ep->emm, ep->l, "can't find 0xf0 in emm...");
		return ERROR; // error
	}

	if (nano9EData) {
		if (!nano91Data) {
			// set adf
			insf0[3] = keynr;  // key
			insf0[4] = nano9EData[1] + 2;
			write_cmd(insf0, nano9EData);
			if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
				cs_dump(insf0, 5, "set adf cmd:");
				cs_dump(nano9EData, insf0[4] , "set adf data:");
				cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
				return ERROR;
			}
		} else {
			// set adf crypte
			insf4[3] = keynr;  // key
			insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
			memcpy (insData, nano91Data, nano91Data[1] + 2);
			memcpy (insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
			write_cmd(insf4, insData);
			if(( cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
				cs_dump(insf4, 5, "set adf encrypted cmd:");
				cs_dump(insData, insf4[4], "set adf encrypted data:");
				cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
				return ERROR;
			}
		}
	}

	if (!nano92Data) {
		// send subscription
		ins18[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
		ins18[3] = keynr;  // key
		ins18[4] = ins18Len + nanoF0Data[1] + 2;
		memcpy (insData, ins18Data, ins18Len);
		memcpy (insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
		write_cmd(ins18, insData);
		if( (cta_res[cta_lr-2]==0x90 || cta_res[cta_lr-2]==0x91) && cta_res[cta_lr-1]==0x00 ) {
			cs_debug_mask(D_READER, "[viaccess-reader] update successfully written");
			rc=1; // written
		} else {
			cs_dump(ins18, 5, "set subscription cmd:");
			cs_dump(insData, ins18[4], "set subscription data:");
			cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
		}

	} else {
		// send subscription encrypted

		if (!nano81Data) {
			cs_dump(ep->emm, ep->l, "0x92 found, but can't find 0x81 in emm...");
			return ERROR; // error
		}

		ins1c[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
		if (ep->type == UNIQUE) ins1c[2] = 0x02;
		ins1c[3] = keynr;  // key
		ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
		memcpy (insData, nano92Data, nano92Data[1] + 2);
		memcpy (insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
		memcpy (insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
		write_cmd(ins1c, insData);

		if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
			cs_log("[viaccess-reader] update successfully written");
			rc=1; // written
		}
		else {
			if( cta_res[cta_lr-2]&0x1 )
				cs_log("[viaccess-reader] update not written. Data already exists or unknown address");

			//if( cta_res[cta_lr-2]&0x8 ) {
			write_cmd(insc8, NULL);
			if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
				cs_log("[viaccess-reader] extended status  %02X %02X", cta_res[0], cta_res[1]);
			}
			//}
			return ERROR;
		}

	}

	/*
	Sub Main()
	Sc.Write("CA A4 04 00 03")
	RX
	Sc.Write("02 07 11")
	RX
	Sc.Write("CA F0 00 01 22")
	RX
	Sc.Write("9E 20")
	Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
	Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
	RX
	Sc.Write("CA 18 01 01 11")
	RX
	Sc.Write("A9 05 34 DE 34 FF 80")
	Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
	RX

	End Sub
	*/
	return rc;
}
示例#20
0
int32_t ICC_Async_Activate (struct s_reader *reader, ATR * atr, uint16_t deprecated)
{
	cs_debug_mask (D_IFD, "IFD: Activating card in reader %s\n", reader->label);

	reader->current_baudrate = DEFAULT_BAUDRATE; //this is needed for all readers to calculate work_etu for timings

	if (reader->atr[0] != 0) {
		cs_log("using ATR from reader config");
		ATR_InitFromArray(atr, reader->atr, ATR_MAX_SIZE);
	}
	else {
		if (reader->crdr.active==1 && reader->crdr.activate) {
			call(reader->crdr.activate(reader, atr));
		} else {

		switch(reader->typ) {
			case R_MP35:
			case R_DB2COM1:
			case R_DB2COM2:
			case R_SC8in1:
			case R_MOUSE:
				LOCK_SC8IN1;
				int32_t ret = Phoenix_Reset(reader, atr);
				UNLOCK_SC8IN1;
				if (ret) {
					cs_debug_mask(D_TRACE, "ERROR, function call Phoenix_Reset returns error.");
					return ERROR;
				}
				break;
#if defined(LIBUSB)
			case R_SMART:
				call (SR_Reset(reader, atr));
				break;
#endif
			case R_INTERNAL:
#if defined(SCI_DEV)
				call (Sci_Activate(reader));
				call (Sci_Reset(reader, atr));
#elif defined(COOL) || defined(SU980)
				call (Cool_Reset(reader,atr));
#if 0
			if ( ! reader->ins7e11_fast_reset) {
				printf("do Cool_Reset\n");
				call (Cool_Reset(reader, atr));
			}
			else {
				printf("do fast reset \n");
				cs_debug_mask(D_DEVICE,"fast reset needed for %s - restoring transmit parameter for coolstream device %s", reader->label, reader->device);
				call(Cool_Set_Transmit_Timeout(reader, 0));
				cs_log("Doing fast reset");
				call (Cool_FastReset_With_ATR(reader, atr));
			}
#endif
#elif defined(WITH_STAPI)
				call (STReader_Reset(reader->stsmart_handle, atr));
#elif defined(AZBOX)
				call (Azbox_Reset(reader, atr));
#endif
				break;
#ifdef HAVE_PCSC
			case R_PCSC:
				 {
					unsigned char atrarr[ATR_MAX_SIZE];
					uint16_t atr_size = 0;
					if (pcsc_activate_card(reader, atrarr, &atr_size))
					{
						if (ATR_InitFromArray (atr, atrarr, atr_size) == ATR_OK)
							return OK;
						else
							return ERROR;
					}
					else
						return ERROR;
				 }
				break;
#endif
			default:
				cs_log("ERROR ICC_Async_Activate: unknow reader type %i",reader->typ);
				return ERROR;
		}
		}
	}

	unsigned char atrarr[ATR_MAX_SIZE];
	uint32_t atr_size;
	ATR_GetRaw(atr, atrarr, &atr_size);
	char tmp[atr_size*3+1];
	cs_ri_log(reader, "ATR: %s", cs_hexdump(1, atrarr, atr_size, tmp, sizeof(tmp)));


	/* Get ICC reader->convention */
	if (ATR_GetConvention (atr, &(reader->convention)) != ATR_OK) {
		cs_log("ERROR: Could not read reader->convention");
		reader->convention = 0;
		reader->protocol_type = 0;
		return ERROR;
	}

	reader->protocol_type = ATR_PROTOCOL_TYPE_T0;

	LOCK_SC8IN1;
	int32_t ret = Parse_ATR(reader, atr, deprecated);
	UNLOCK_SC8IN1; //Parse_ATR and InitCard need to be included in lock because they change parity of serial port
	if (ret)
		cs_log("ERROR: Parse_ATR returned error");
	if (ret)
		return ERROR;
	cs_debug_mask (D_IFD, "IFD: Card in reader %s succesfully activated\n", reader->label);

	return OK;
}
示例#21
0
int32_t viaccess_reassemble_emm(uchar *buffer, uint32_t *len) {
	static uchar emm_global[512];
	static int32_t emm_global_len = 0;

	int32_t pos=0, i;
	uint32_t k;

	// Viaccess
	if (*len>500) return 0;

	switch(buffer[0]) {
		case 0x8c:
		case 0x8d:
			// emm-s part 1
			if (!memcmp(emm_global, buffer, *len))
				return 0;

			// copy first part of the emm-s
			memcpy(emm_global, buffer, *len);
			emm_global_len=*len;
			//cs_ddump_mask(D_READER, buffer, len, "viaccess global emm:");
			return 0;

		case 0x8e:
			// emm-s part 2
			if (!emm_global_len) return 0;

			//extract nanos from emm-gh and emm-s
			uchar emmbuf[512];

			cs_debug_mask(D_DVBAPI, "viaccess_reassemble_emm: start extracting nanos");
			//extract from emm-gh
			for (i=3; i<emm_global_len; i+=emm_global[i+1]+2) {
				//copy nano (length determined by i+1)
				memcpy(emmbuf+pos, emm_global+i, emm_global[i+1]+2);
				pos+=emm_global[i+1]+2;
			}

			if (buffer[2]==0x2c) {
				//add 9E 20 nano + first 32 bytes of emm content
				memcpy(emmbuf+pos, "\x9E\x20", 2);
				memcpy(emmbuf+pos+2, buffer+7, 32);
				pos+=34;

				//add F0 08 nano + 8 subsequent bytes of emm content
				memcpy(emmbuf+pos, "\xF0\x08", 2);
				memcpy(emmbuf+pos+2, buffer+39, 8);
				pos+=10;
			} else {
				//extract from variable emm-s
				for (k=7; k<(*len); k+=buffer[k+1]+2) {
					//copy nano (length determined by k+1)
					memcpy(emmbuf+pos, buffer+k, buffer[k+1]+2);
					pos+=buffer[k+1]+2;
				}
			}

			cs_ddump_mask(D_DVBAPI, buffer, *len, "viaccess_reassemble_emm: %s emm-s", (buffer[2]==0x2c) ? "fixed" : "variable");

			dvbapi_sort_nanos(buffer+7, emmbuf, pos);
			pos+=7;

			//calculate emm length and set it on position 2
			buffer[2]=pos-3;

			cs_ddump_mask(D_DVBAPI, emm_global, emm_global_len, "viaccess_reassemble_emm: emm-gh");
			cs_ddump_mask(D_DVBAPI, buffer, pos, "viaccess_reassemble_emm: assembled emm");

			*len=pos;
			break;
	}
	return 1;
}
示例#22
0
static int32_t Parse_ATR (struct s_reader * reader, ATR * atr, uint16_t deprecated)
{
	BYTE FI = ATR_DEFAULT_FI;
	//BYTE t = ATR_PROTOCOL_TYPE_T0;
	double d = ATR_DEFAULT_D;
	double n = ATR_DEFAULT_N;
	int32_t ret;
	char tmp[256];

		int32_t numprot = atr->pn;
		//if there is a trailing TD, this number is one too high
		BYTE tx;
		if (ATR_GetInterfaceByte (atr, numprot-1, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK)
			if ((tx & 0xF0) == 0)
				numprot--;
		int32_t i,point;
		char txt[50];
		bool OffersT[3]; //T14 stored as T2
		for (i = 0; i <= 2; i++)
			OffersT[i] = FALSE;
		for (i=1; i<= numprot; i++) {
			point = 0;
			if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TA, &tx) == ATR_OK) {
				snprintf((char *)txt+point,sizeof(txt)-point,"TA%i=%02X ",i,tx);
				point +=7;
			}
			if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TB, &tx) == ATR_OK) {
				snprintf((char *)txt+point,sizeof(txt)-point,"TB%i=%02X ",i,tx);
				point +=7;
			}
			if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TC, &tx) == ATR_OK) {
				snprintf((char *)txt+point,sizeof(txt)-point,"TC%i=%02X ",i,tx);
				point +=7;
			}
			if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK) {
				snprintf((char *)txt+point,sizeof(txt)-point,"TD%i=%02X ",i,tx);
				point +=7;
				tx &= 0X0F;
				snprintf((char *)txt+point,sizeof(txt)-point,"(T%i)",tx);
				if (tx == 14)
					OffersT[2] = TRUE;
				else
					OffersT[tx] = TRUE;
			}
			else {
				snprintf((char *)txt+point,sizeof(txt)-point,"no TD%i means T0",i);
				OffersT[0] = TRUE;
			}
			cs_debug_mask(D_ATR, "%s",txt);
		}

		int32_t numprottype = 0;
		for (i = 0; i <= 2; i++)
			if (OffersT[i])
				numprottype ++;
		cs_debug_mask(D_ATR, "%i protocol types detected. Historical bytes: %s",numprottype, cs_hexdump(1,atr->hb,atr->hbn, tmp, sizeof(tmp)));

		ATR_GetParameter (atr, ATR_PARAMETER_N, &(n));
		ATR_GetProtocolType(atr,1,&(reader->protocol_type)); //get protocol from TD1
		BYTE TA2;
		bool SpecificMode = (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TA, &TA2) == ATR_OK); //if TA2 present, specific mode, else negotiable mode
		if (SpecificMode) {
			reader->protocol_type = TA2 & 0x0F;
			if ((TA2 & 0x10) != 0x10) { //bit 5 set to 0 means F and D explicitly defined in interface characters
				BYTE TA1;
				if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
					FI = TA1 >> 4;
					ATR_GetParameter (atr, ATR_PARAMETER_D, &(d));
				}
				else {
示例#23
0
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;
}
示例#24
0
int32_t Protocol_T1_Command (struct s_reader *reader, unsigned char * command, uint16_t command_len, unsigned char * rsp, uint16_t * lr)
{
  T1_Block *block;
  BYTE *buffer, rsp_type, bytes, nr, wtx;
  uint16_t counter;
  int32_t ret;
  bool more;
  if (command[1] == T1_BLOCK_S_IFS_REQ)
  {
    BYTE inf = command[3];

    /* Create an IFS request S-Block */
    block = T1_Block_NewSBlock (T1_BLOCK_S_IFS_REQ, 1, &inf);
    cs_debug_mask (D_IFD, "Protocol: Sending block S(IFS request, %d)", inf);

    /* Send IFSD request */
    ret = Protocol_T1_SendBlock (reader, block);

    /* Receive a block */
    ret = Protocol_T1_ReceiveBlock (reader, &block);

    if (ret == OK)
      {
        rsp_type = T1_Block_GetType (block);

        /* Positive IFS Response S-Block received */
        if (rsp_type == T1_BLOCK_S_IFS_RES)
          {
            /* Update IFSD value */
            inf = (*T1_Block_GetInf (block));
            cs_debug_mask (D_IFD, "Protocol: Received block S(IFS response, %d)", inf);
          }
        T1_Block_Delete (block);
      }

    return ret;
  }

  if (command[1] == T1_BLOCK_S_RESYNCH_REQ)
  {
    /* Create an Resynch request S-Block */
    block = T1_Block_NewSBlock (T1_BLOCK_S_RESYNCH_REQ, 0, NULL);
    cs_debug_mask (D_IFD, "Protocol: Sending block S(RESYNCH request)");

    /* Send request */
    ret = Protocol_T1_SendBlock (reader, block);

    /* Receive a block */
    ret = Protocol_T1_ReceiveBlock (reader, &block);

    if (ret == OK)
      {
        rsp_type = T1_Block_GetType (block);

        /* Positive IFS Response S-Block received */
        if (rsp_type == T1_BLOCK_S_RESYNCH_RES) {
            cs_debug_mask (D_IFD, "Protocol: Received block S(RESYNCH response)");
						reader->ns = 0;
				}
		T1_Block_Delete (block);
      }

    return ret;
  }

  /* Calculate the number of bytes to send */
  counter = 0;
  bytes = MIN (command_len, reader->ifsc);

  /* See if chaining is needed */
  more = (command_len > reader->ifsc);

  /* Increment ns */
  reader->ns = (reader->ns == 1) ? 0:1; //toggle from 0 to 1 and back

  /* Create an I-Block */
  block = T1_Block_NewIBlock (bytes, command, reader->ns, more);
  cs_debug_mask (D_IFD, "Sending block I(%d,%d)", reader->ns, more);

  /* Send a block */
  call (Protocol_T1_SendBlock (reader, block));

  while (more) {
      /* Receive a block */
      call (Protocol_T1_ReceiveBlock (reader, &block));
      rsp_type = T1_Block_GetType (block);

      /* Positive ACK R-Block received */
      if (rsp_type == T1_BLOCK_R_OK) {
          cs_debug_mask (D_IFD, "Protocol: Received block R(%d)", T1_Block_GetNR (block));
          /* Delete block */
          T1_Block_Delete (block);
 
          /* Increment ns  */
          reader->ns = (reader->ns == 1) ? 0:1; //toggle from 0 to 1 and back

          /* Calculate the number of bytes to send */
          counter += bytes;
          bytes = MIN (command_len - counter, reader->ifsc);

          /* See if chaining is needed */
          more = (command_len - counter > reader->ifsc);

          /* Create an I-Block */
          block = T1_Block_NewIBlock (bytes, command + counter, reader->ns, more);
          cs_debug_mask (D_IFD, "Protocol: Sending block I(%d,%d)", reader->ns, more);

          /* Send a block */
          call (Protocol_T1_SendBlock (reader, block));
      }
      else {
          /* Delete block */
          T1_Block_Delete (block);
          cs_debug_mask(D_TRACE, "ERROR T1 Command %02X not implemented in SendBlock", rsp_type);
          return ERROR;
      }
  }

  /* Reset counter */
	ret = OK;
  buffer = NULL;
  counter = 0;      
  more = TRUE;
  wtx = 0;
      
  while ((ret == OK) && more)
    {
      if (wtx > 1)
        ICC_Async_SetTimings (reader, wtx * reader->BWT);

      /* Receive a block */
      ret = Protocol_T1_ReceiveBlock (reader, &block);

      if (wtx > 1)
        {
          ICC_Async_SetTimings (reader, reader->BWT);          
          wtx = 0;
        }

      if (ret == OK)
        {
          rsp_type = T1_Block_GetType (block);

          if (rsp_type == T1_BLOCK_I)
            {
              cs_debug_mask (D_IFD, "Protocol: Received block I(%d,%d)", 
              T1_Block_GetNS(block), T1_Block_GetMore (block));
              /* Calculate nr */
              nr = (T1_Block_GetNS (block) + 1) % 2;
                               
              /* Save inf field */
              bytes = T1_Block_GetLen (block);
      	      buffer = (BYTE *) realloc(buffer, counter + bytes);
              memcpy (buffer + counter, T1_Block_GetInf (block), bytes);
              counter += bytes;

              /* See if chaining is requested */
              more = T1_Block_GetMore (block);

              /* Delete block */
              T1_Block_Delete (block);

              if (more)
                {
                  /* Create an R-Block */
                  block = T1_Block_NewRBlock (T1_BLOCK_R_OK, nr);
                  cs_debug_mask (D_IFD, "Protocol: Sending block R(%d)", nr);

                  /* Send R-Block */
                  ret = Protocol_T1_SendBlock (reader, block);
                }
            }

          /* WTX Request S-Block received */ 
          else if (rsp_type == T1_BLOCK_S_WTX_REQ)
            {
              /* Get wtx multiplier */
              wtx = (*T1_Block_GetInf (block));
              cs_debug_mask (D_IFD, "Protocol: Received block S(WTX request, %d)", wtx);

              /* Delete block */
              T1_Block_Delete (block);
             
              /* Create an WTX response S-Block */
              block = T1_Block_NewSBlock (T1_BLOCK_S_WTX_RES, 1, &wtx);
              cs_debug_mask (D_IFD, "Protocol: Sending block S(WTX response, %d)", wtx);

              /* Send WTX response */
              ret = Protocol_T1_SendBlock (reader, block);
            }

          else
            {
              cs_debug_mask(D_TRACE, "ERROR T1 Command %02X not implemented in Receive Block", rsp_type);
              ret = ERROR;//not implemented
            }
        }
    }

  if (ret == OK) {
		memcpy(rsp, buffer, counter);
		*lr = counter;
	}

  if (buffer != NULL)
    free (buffer);
  
  return ret;
}
示例#25
0
int32_t coolapi_remove_filter (int32_t fd, int32_t num)
{
	dmx_t * dmx = find_demux(fd, 0);
	if(!dmx) {
		 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
		 return -1;
	}

	if(dmx->pid <= 0)
		return -1;

	int32_t result, filter_on_channel=0;

    cs_debug_mask(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04x on channel=%x", fd, num, dmx->pid, (int32_t) dmx->channel);

	pthread_mutex_lock(&dmx->mutex);

	if(dmx->filter) {
		result = cnxt_dmx_channel_detach_filter(dmx->channel, dmx->filter);
		coolapi_check_error("cnxt_dmx_channel_detach_filter", result);
		result = cnxt_dmx_close_filter(dmx->filter);
		coolapi_check_error("cnxt_dmx_close_filter", result);
		dmx->filter = NULL;
		result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0);
		coolapi_check_error("cnxt_dmx_channel_ctrl", result);
	}

	LL_ITER itr = ll_iter_create(ll_cool_filter);
	S_COOL_FILTER *filter_item;
	while ((filter_item=ll_iter_next(&itr))) {
		if (filter_item->channel == (int32_t) dmx->channel)
			filter_on_channel++;
		if (filter_item->fd == fd) {
			ll_iter_remove_data(&itr);
			filter_on_channel--;
		}
	}

	if (!filter_on_channel) {
		cs_debug_mask(D_DVBAPI, "closing channel %x", (int32_t) dmx->channel);

		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 == dmx->pid) {
				dmx->buffer1=handle_item->buffer1;
				dmx->buffer2=handle_item->buffer2;
				ll_iter_remove_data(&itr);
				break;
			}
		}

		if (!dmx->buffer1 || !dmx->buffer2)
			cs_debug_mask(D_DVBAPI, "WARNING: buffer handle not found!");

		result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0);
		coolapi_check_error("cnxt_dmx_channel_ctrl", result);

		result = cnxt_dmx_set_channel_pid(dmx->channel, 0x1FFF);
		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);

		result = cnxt_cbuf_detach(dmx->buffer2, 2, dmx->channel);
		coolapi_check_error("cnxt_cbuf_detach", result);
		result = cnxt_dmx_channel_detach(dmx->channel, 0xB, 0, dmx->buffer1);
		coolapi_check_error("cnxt_dmx_channel_detach", result);

		result = cnxt_dmx_channel_close(dmx->channel);
		coolapi_check_error("cnxt_dmx_channel_close", result);

		result = cnxt_cbuf_close(dmx->buffer2);
		coolapi_check_error("cnxt_cbuf_close", result);

		result = cnxt_cbuf_close(dmx->buffer1);
		coolapi_check_error("cnxt_cbuf_close", result);
	}

	if (filter_on_channel) {
		result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0);
		coolapi_check_error("cnxt_dmx_channel_ctrl", result);
	}

	pthread_mutex_unlock(&dmx->mutex);

	dmx->pid = -1;
	return 0;
}
示例#26
0
static int32_t oscam_ser_check_ecm(ECM_REQUEST *er, uchar *buf, int32_t l)
{
	int32_t i;
	struct s_serial_client *serialdata = cur_client()->serialdata;

	if(l < 16)
	{
		cs_log(incomplete, l);
		return (1);
	}

	switch(serialdata->connected)
	{
	case P_HSIC:
		er->ecmlen = l - 12;
		er->caid = b2i(2, buf + 1);
		er->prid = b2i(3, buf + 3);
		er->pid  = b2i(2, buf + 6);
		er->srvid = b2i(2, buf + 10);
		memcpy(er->ecm, buf + 12, er->ecmlen);
		break;
	case P_SSSP:
		er->pid = b2i(2, buf + 3);
		for(i = 0; (i < 8) && (serialdata->sssp_tab[i].pid != er->pid); i++) { ; }
		if(i >= serialdata->sssp_num)
		{
			cs_debug_mask(D_CLIENT, "illegal request, unknown pid=%04X", er->pid);
			return (2);
		}
		er->ecmlen = l - 5;
		er->srvid = serialdata->sssp_srvid;
		er->caid = serialdata->sssp_tab[i].caid;
		er->prid = serialdata->sssp_tab[i].prid;
		memcpy(er->ecm, buf + 5, er->ecmlen);
		break;
	case P_BOMBA:
		er->ecmlen = l;
		memcpy(er->ecm, buf, er->ecmlen);
		break;
	case P_DSR95:
		buf[l] = '\0'; // prepare for trim
		trim((char *)buf + 13); // strip spc, nl, cr ...
		er->ecmlen = strlen((char *)buf + 13) >> 1;
		er->prid = cs_atoi((char *)buf + 3, 3, 0); // ignore errors
		er->caid = cs_atoi((char *)buf + 9, 2, 0); // ignore errors
		if(cs_atob(er->ecm, (char *)buf + 13, er->ecmlen) < 0)
		{
			cs_log("illegal characters in ecm-request");
			return (1);
		}
		if(serialdata->dsr9500type == P_DSR_WITHSID)
		{
			er->ecmlen -= 2;
			er->srvid = cs_atoi((char *)buf + 13 + (er->ecmlen << 1), 2, 0);
		}
		break;
	case P_GS:
		er->ecmlen = ((buf[3] << 8) | buf[2]) - 6;
		er->srvid = (buf[5] << 8) | buf[4];  // sid
		er->caid  = (buf[7] << 8) | buf[6];
		er->prid  = 0;
		if(er->ecmlen > 256) { er->ecmlen = 256; }
		memcpy(er->ecm, buf + 10, er->ecmlen);
		break;
	case P_ALPHA:
		l = oscam_ser_alpha_convert(buf, l);
		er->ecmlen = b2i(2, buf + 1) - 2;
		er->caid  = b2i(2, buf + 3);
		if((er->ecmlen != l - 5) || (er->ecmlen > 257))
		{
			cs_log(incomplete, l);
			return (1);
		}
		memcpy(er->ecm, buf + 5, er->ecmlen);
		break;
	case P_GBOX:
		er->srvid = b2i(2, buf + serialdata->gbox_lens.cat_len + 3 + 3);
		er->ecmlen = serialdata->gbox_lens.ecm_len + 3;
		memcpy(er->ecm, buf + serialdata->gbox_lens.cat_len + 3 + serialdata->gbox_lens.pmt_len + 3, er->ecmlen);
		break;
	}
	return (0);
}
示例#27
0
文件: oscam.c 项目: StbLinux/oscam
static void process_clients(void)
{
	int32_t i, k, j, rc, pfdcount = 0;
	struct s_client *cl;
	struct s_reader *rdr;
	struct pollfd *pfd;
	struct s_client **cl_list;
	struct timeb start, end;  // start time poll, end time poll
	uint32_t cl_size = 0;

	uchar buf[10];

	if(pipe(thread_pipe) == -1)
	{
		printf("cannot create pipe, errno=%d\n", errno);
		exit(1);
	}

	cl_size = chk_resize_cllist(&pfd, &cl_list, 0, 100);

	pfd[pfdcount].fd = thread_pipe[0];
	pfd[pfdcount].events = POLLIN | POLLPRI;
	cl_list[pfdcount] = NULL;

	while(!exit_oscam)
	{
		pfdcount = 1;

		//connected tcp clients
		for(cl = first_client->next; cl; cl = cl->next)
		{
			if(cl->init_done && !cl->kill && cl->pfd && cl->typ == 'c' && !cl->is_udp)
			{
				if(cl->pfd && !cl->thread_active)
				{
					cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
					cl_list[pfdcount] = cl;
					pfd[pfdcount].fd = cl->pfd;
					pfd[pfdcount++].events = POLLIN | POLLPRI;
				}
			}
			//reader:
			//TCP:
			//  - TCP socket must be connected
			//  - no active init thread
			//UDP:
			//  - connection status ignored
			//  - no active init thread
			rdr = cl->reader;
			if(rdr && cl->typ == 'p' && cl->init_done)
			{
				if(cl->pfd && !cl->thread_active && ((rdr->tcp_connected && rdr->ph.type == MOD_CONN_TCP) || (rdr->ph.type == MOD_CONN_UDP)))
				{
					cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
					cl_list[pfdcount] = cl;
					pfd[pfdcount].fd = cl->pfd;
					pfd[pfdcount++].events = (POLLIN | POLLPRI);
				}
			}
		}

		//server (new tcp connections or udp messages)
		for(k = 0; k < CS_MAX_MOD; k++)
		{
			struct s_module *module = &modules[k];
			if((module->type & MOD_CONN_NET))
			{
				for(j = 0; j < module->ptab.nports; j++)
				{
					if(module->ptab.ports[j].fd)
					{
						cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
						cl_list[pfdcount] = NULL;
						pfd[pfdcount].fd = module->ptab.ports[j].fd;
						pfd[pfdcount++].events = (POLLIN | POLLPRI);
					}
				}
			}
		}

		if(pfdcount >= 1024)
			{ cs_log("WARNING: too many users!"); }
		cs_ftime(&start); // register start time
		rc = poll(pfd, pfdcount, 5000);
		if(rc < 1) { continue; }
		cs_ftime(&end); // register end time

		for(i = 0; i < pfdcount && rc > 0; i++)
		{
			if(pfd[i].revents == 0) { continue; }  // skip sockets with no changes
			rc--; //event handled!
			cs_debug_mask(D_TRACE, "[OSCAM] new event %d occurred on fd %d after %ld ms inactivity", pfd[i].revents,
						  pfd[i].fd, 1000 * (end.time - start.time) + end.millitm - start.millitm);
			//clients
			cl = cl_list[i];
			if(cl && !is_valid_client(cl))
				{ continue; }

			if(pfd[i].fd == thread_pipe[0] && (pfd[i].revents & (POLLIN | POLLPRI)))
			{
				// a thread ended and cl->pfd should be added to pollfd list again (thread_active==0)
				int32_t len = read(thread_pipe[0], buf, sizeof(buf));
				if(len == -1)
				{
					cs_debug_mask(D_TRACE, "[OSCAM] Reading from pipe failed (errno=%d %s)", errno, strerror(errno));
				}
				cs_ddump_mask(D_TRACE, buf, len, "[OSCAM] Readed:");
				continue;
			}

			//clients
			// message on an open tcp connection
			if(cl && cl->init_done && cl->pfd && (cl->typ == 'c' || cl->typ == 'm'))
			{
				if(pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
				{
					//client disconnects
					kill_thread(cl);
					continue;
				}
				if(pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLIN | POLLPRI)))
				{
					add_job(cl, ACTION_CLIENT_TCP, NULL, 0);
				}
			}


			//reader
			// either an ecm answer, a keepalive or connection closed from a proxy
			// physical reader ('r') should never send data without request
			rdr = NULL;
			struct s_client *cl2 = NULL;
			if(cl && cl->typ == 'p')
			{
				rdr = cl->reader;
				if(rdr)
					{ cl2 = rdr->client; }
			}

			if(rdr && cl2 && cl2->init_done)
			{
				if(cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
				{
					//connection to remote proxy was closed
					//oscam should check for rdr->tcp_connected and reconnect on next ecm request sent to the proxy
					network_tcp_connection_close(rdr, "closed");
					rdr_debug_mask(rdr, D_READER, "connection closed");
				}
				if(cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLIN | POLLPRI)))
				{
					add_job(cl2, ACTION_READER_REMOTE, NULL, 0);
				}
			}


			//server sockets
			// new connection on a tcp listen socket or new message on udp listen socket
			if(!cl && (pfd[i].revents & (POLLIN | POLLPRI)))
			{
				for(k = 0; k < CS_MAX_MOD; k++)
				{
					struct s_module *module = &modules[k];
					if((module->type & MOD_CONN_NET))
					{
						for(j = 0; j < module->ptab.nports; j++)
						{
							if(module->ptab.ports[j].fd && module->ptab.ports[j].fd == pfd[i].fd)
							{
								accept_connection(module, k, j);
							}
						}
					}
				}
			}
		}
		cs_ftime(&start); // register start time for new poll next run
		first_client->last = time((time_t *)0);
	}
	free(pfd);
	free(cl_list);
	return;
}