Esempio n. 1
0
int32_t ICC_Async_Receive (struct s_reader *reader, uint32_t size, BYTE * data)
{

	if (reader->crdr.active==1) {
		call(reader->crdr.receive(reader, data, size));

		if (reader->convention == ATR_CONVENTION_INVERSE && reader->crdr.need_inverse==1)
			ICC_Async_InvertBuffer (size, data);

		cs_ddump_mask(D_IFD, data, size, "IFD Received: ");
		return OK;
	}

	switch(reader->typ) {
		case R_MP35:
		case R_DB2COM1:
		case R_DB2COM2:
		case R_SC8in1:
		case R_MOUSE:
			call (Phoenix_Receive (reader, data, size, reader->read_timeout));
			break;
#if defined(LIBUSB)
		case R_SMART:
			call (SR_Receive(reader, data, size));
			break;
#endif
		case R_INTERNAL:
#if defined(COOL)
			call (Cool_Receive(data, size));
#elif defined(AZBOX)
			call (Azbox_Receive(reader, data, size));
#elif defined(SCI_DEV)
			call (Phoenix_Receive (reader, data, size, reader->read_timeout));
#elif defined(WITH_STAPI)
			call (STReader_Receive(reader->stsmart_handle, data, size));
#endif
			break;
		default:
			cs_log("ERROR ICC_Async_Receive: unknow reader type %i",reader->typ);
			return ERROR;
	}

	if (reader->convention == ATR_CONVENTION_INVERSE && reader->typ <= R_MOUSE)
		ICC_Async_InvertBuffer (size, data);

	cs_ddump_mask(D_IFD, data, size, "IFD Received: ");
	return OK;
}
Esempio n. 2
0
int32_t Cool_Transmit (BYTE * sent, uint32_t size)
{ 
	specdev()->cardbuflen = 256;//it needs to know max buffer size to respond?
	call (cnxt_smc_read_write(specdev()->handle, FALSE, sent, size, specdev()->cardbuffer, &specdev()->cardbuflen, 50, 0));
	//call (cnxt_smc_read_write(specdev()->handle, FALSE, sent, size, specdev()->cardbuffer, &specdev()->cardbuflen, read_timeout, 0));
	cs_ddump_mask(D_DEVICE, sent, size, "COOL IO: Transmit: ");
	return OK;
}
Esempio n. 3
0
int32_t ICC_Async_CardWrite (struct s_reader *reader, unsigned char *command, uint16_t command_len, unsigned char *rsp, uint16_t *lr)
{
#ifdef HAVE_PCSC
	if (reader->typ == R_PCSC)
 	  return (pcsc_reader_do_api(reader, command, rsp, lr, command_len));
#endif
	*lr = 0; //will be returned in case of error

	int32_t ret;

	LOCK_SC8IN1;

	int32_t try = 1;
	do {
	 switch (reader->protocol_type) {
		if (try > 1)
			cs_log("Warning: reader %s needed try nr %i, next ECM has some delay:", reader->label, try);
		case ATR_PROTOCOL_TYPE_T0:
			ret = Protocol_T0_Command (reader, command, command_len, rsp, lr);
			break;
		case ATR_PROTOCOL_TYPE_T1:
			ret = Protocol_T1_Command (reader, command, command_len, rsp, lr);
			if (ret != OK) {
				//try to resync
				unsigned char resync[] = { 0x21, 0xC0, 0x00, 0xE1 };
				Protocol_T1_Command (reader, resync, sizeof(resync), rsp, lr);
				reader->ifsc = DEFAULT_IFSC;
			}
			break;
		case ATR_PROTOCOL_TYPE_T14:
			ret = Protocol_T14_ExchangeTPDU (reader, command, command_len, rsp, lr);
			break;
		default:
			cs_log("Error, unknown protocol type %i",reader->protocol_type);
			ret = ERROR;
	 }
	try++;
	} while ((try < 3) && (ret != OK)); //always do one retry when failing

	UNLOCK_SC8IN1;

	if (ret) {
		cs_debug_mask(D_TRACE, "ERROR, function call Protocol_T0_Command returns error.");
		return ERROR;
	}

	cs_ddump_mask(D_READER, rsp, *lr, "answer from cardreader %s:", reader->label);
	return OK;
}

int32_t ICC_Async_SetTimings (struct s_reader * reader, uint32_t wait_etu)
{
	reader->read_timeout = ETU_to_ms(reader, wait_etu);
	cs_debug_mask(D_IFD, "Setting timeout to %i", wait_etu);
	return OK;
}
Esempio n. 4
0
int32_t Cool_Transmit (struct s_reader *reader, BYTE * sent, uint32_t size)
{ 
	specdev()->cardbuflen = 256;//it needs to know max buffer size to respond?

	int32_t ret = cnxt_smc_read_write(specdev()->handle, FALSE, sent, size, specdev()->cardbuffer, &specdev()->cardbuflen, specdev()->read_write_transmit_timeout, 0);
	check_error("cnxt_smc_read_write", ret);

	cs_ddump_mask(D_DEVICE, sent, size, "COOL IO: Transmit: ");	
	return OK;
}
Esempio n. 5
0
int32_t Cool_Receive (struct s_reader *reader, BYTE * data, uint32_t size)
{ 
	if (size > specdev()->cardbuflen)
		size = specdev()->cardbuflen; //never read past end of buffer
	memcpy(data, specdev()->cardbuffer, size);
	specdev()->cardbuflen -= size;
	memmove(specdev()->cardbuffer, specdev()->cardbuffer+size, specdev()->cardbuflen);
	cs_ddump_mask(D_DEVICE, data, size, "COOL IO: Receive: ");
	return OK;
}	
Esempio n. 6
0
static int32_t camd33_send(uchar *buf, int32_t ml)
{
  int32_t l;
  if (!cur_client()->pfd) return(-1);
  l=boundary(4, ml);
  memset(buf+ml, 0, l-ml);
  cs_ddump_mask(D_CLIENT, buf, l, "send %d bytes to client", l);
  if (cur_client()->crypted)
    aes_encrypt(buf, l);
  return(send(cur_client()->pfd, buf, l, 0));
}
Esempio n. 7
0
static int32_t camd33_recv(struct s_client * client, uchar *buf, int32_t l)
{
  int32_t n;
  if (!client->pfd) return(-1);
  if ((n=recv(client->pfd, buf, l, 0))>0)
  {
    client->last=time((time_t *) 0);
    if (client->crypted)
      aes_decrypt(buf, n);
  }
  cs_ddump_mask(D_CLIENT, buf, n, "received %d bytes from client", n);
  return(n);
}
Esempio n. 8
0
void cardreader_process_ecm(struct s_reader *reader, struct s_client *cl, ECM_REQUEST *er) {
	if (ecm_ratelimit_check(reader, er, 1) != OK) {
		rdr_debug_mask(reader, D_READER, "%s: ratelimit check failed.", __func__);
		return; // reader_mode = 1: checkout ratelimiter in reader mode so srvid can be replaced
	}
	cs_ddump_mask(D_ATR, er->ecm, er->ecmlen, "ecm:");

	struct timeb tps, tpe;
	cs_ftime(&tps);

	struct s_ecm_answer ea;
	memset(&ea, 0, sizeof(struct s_ecm_answer));

	int32_t rc = cardreader_do_ecm(reader, er, &ea);
	rdr_debug_mask(reader, D_READER, "%s: cardreader_do_ecm returned rc=%d (ERROR=%d)", __func__, rc, ERROR);

	ea.rc = E_FOUND; //default assume found
	ea.rcEx = 0; //no special flag

	if (rc == ERROR) {
		char buf[32];
		rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s",
			er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf));
		ea.rc = E_NOTFOUND;
		ea.rcEx = 0;
		ICC_Async_DisplayMsg(reader, "Eer");
	}

	if (rc == E_CORRUPT) {
		char buf[32];
		rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s",
			er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf));
		ea.rc = E_NOTFOUND;
		ea.rcEx = E2_WRONG_CHKSUM; //flag it as wrong checksum
		memcpy (ea.msglog,"Invalid ecm type for card",25);
	}
	cs_ftime(&tpe);
	cl->lastecm=time((time_t*)0);
	char ecmd5[17*3];                
    cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5));

	rdr_debug_mask(reader, D_READER, "ecm hash: %s real time: %ld ms",
		ecmd5, 1000 * (tpe.time - tps.time) + tpe.millitm - tps.millitm);

	write_ecm_answer(reader, er, ea.rc, ea.rcEx, ea.cw, ea.msglog);

	reader_post_process(reader);
}
Esempio n. 9
0
static int32_t radegast_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *UNUSED(buf))
{
	int32_t n;
	uchar provid_buf[8];
	uchar header[22] = "\x02\x01\x00\x06\x08\x30\x30\x30\x30\x30\x30\x30\x30\x07\x04\x30\x30\x30\x38\x08\x01\x02";
	uchar *ecmbuf;

	if(!radegast_connect())
		{ return (-1); }

	if(!cs_malloc(&ecmbuf, er->ecmlen + 30))
		{ return -1; }

	ecmbuf[0] = 1;
	ecmbuf[1] = (er->ecmlen + 30 - 2) & 0xff;
	memcpy(ecmbuf + 2, header, sizeof(header));
	for(n = 0; n < 4; n++)
	{
		snprintf((char *)provid_buf + (n * 2), sizeof(provid_buf) - (n * 2), "%02X", ((uchar *)(&er->prid))[4 - 1 - n]);
	}
	ecmbuf[7] = provid_buf[0];
	ecmbuf[8] = provid_buf[1];
	ecmbuf[9] = provid_buf[2];
	ecmbuf[10] = provid_buf[3];
	ecmbuf[11] = provid_buf[4];
	ecmbuf[12] = provid_buf[5];
	ecmbuf[13] = provid_buf[6];
	ecmbuf[14] = provid_buf[7];
	ecmbuf[2 + sizeof(header)] = 0xa;
	ecmbuf[3 + sizeof(header)] = 2;
	ecmbuf[4 + sizeof(header)] = er->caid >> 8;
	ecmbuf[5 + sizeof(header)] = er->caid & 0xff;
	ecmbuf[6 + sizeof(header)] = 3;
	ecmbuf[7 + sizeof(header)] = er->ecmlen & 0xff;
	memcpy(ecmbuf + 8 + sizeof(header), er->ecm, er->ecmlen);
	ecmbuf[4] = er->caid >> 8;

	client->reader->msg_idx = er->idx;
	n = send(client->pfd, ecmbuf, er->ecmlen + 30, 0);

	cs_debug_mask(D_TRACE, "radegast: sending ecm");
	cs_ddump_mask(D_CLIENT, ecmbuf, er->ecmlen + 30, "ecm:");
	NULLFREE(ecmbuf);
	return ((n < 1) ? (-1) : 0);
}
Esempio n. 10
0
static int32_t get_request(uchar *buf)
{
  int32_t n, rc=0;
  if ((n=process_input(buf, 2, cfg.cmaxidle))==2)
  {
    if ((n=process_input(buf+2, buf[1], 0))>=0)
      n+=2;
    if (n-2==buf[1])
      rc=n;
    else
      cs_log("WARNING: protocol error (garbage)");
  }
  if (n>0)
  {
    cs_ddump_mask(D_CLIENT, buf, n, "received %d bytes from client", n);
  }
  return(rc);
}
Esempio n. 11
0
static int32_t oscam_ser_send(struct s_client *client, const uchar * const buf, int32_t l)
{
  int32_t n;
  struct s_serial_client *serialdata=client->serialdata ;
  if (!client->pfd) return(0);
  cs_ftime(&serialdata->tps);
  serialdata->tpe=client->serialdata->tps;
  serialdata->tpe.millitm+=serialdata->oscam_ser_timeout+(l*(serialdata->oscam_ser_delay+1));
  serialdata->tpe.time+=(serialdata->tpe.millitm/1000);
  serialdata->tpe.millitm%=1000;
  n=oscam_ser_write(client, buf, l);
  cs_ftime(&serialdata->tpe);
  cs_ddump_mask(D_CLIENT, buf, l, "send %d of %d bytes to %s in %ld msec", n, l, remote_txt(),
                    1000*(serialdata->tpe.time-serialdata->tps.time)+serialdata->tpe.millitm-serialdata->tps.millitm);
  if (n!=l)
    cs_log("transmit error. send %d of %d bytes only !", n, l);
  return(n);
}
Esempio n. 12
0
static int32_t radegast_recv(struct s_client *client, uchar *buf, int32_t l)
{
  int32_t n;
  if (!client->pfd) return(-1);
  if (client->typ == 'c') {  // server code
    if ((n=recv(client->pfd, buf, l, 0))>0)
      client->last=time((time_t *) 0);
  } else {  // client code
    if ((n=recv(client->pfd, buf, l, 0))>0) {
      cs_ddump_mask(D_CLIENT, buf, n, "radegast: received %d bytes from %s", n, remote_txt());
      client->last = time((time_t *) 0);
      if ((buf[0] == 0x02)&&(buf[1] == 0x12) && (buf[2] == 0x05)&&(buf[3] == 0x10)) return(n);  // dcw received
      else if ((buf[0] == 0x02)&&(buf[1] == 0x02) && (buf[2] == 0x04)&&(buf[3] == 0x00)) return(n);  // dcw no found
      else if ((buf[0] == 0x81)&&(buf[1] == 0x00)) return(n);  // cmd unknown
      else n = -1;// no cmd radegast disconnect
    }
  }
  return(n);
}
Esempio n. 13
0
static int32_t radegast_recv(struct s_client *client, uchar *buf, int32_t l)
{
  int32_t n;
  if (!client->pfd) return(-1);
  if (client->typ == 'c') {  // server code
    if ((n=recv(client->pfd, buf, l, 0))>0)
      client->last=time((time_t *) 0);
  } else {  // client code
    if ((n=recv(client->pfd, buf, l, 0))>0) {
      cs_ddump_mask(D_CLIENT, buf, n, "radegast: received %d bytes from %s", n, remote_txt());
      client->last = time((time_t *) 0);

      if (buf[0] == 2) {  // dcw received
        if (buf[3] != 0x10) {  // dcw ok
          cs_log("radegast: no dcw");
          n = -1;
        }
      }
    }
  }
  return(n);
}
Esempio n. 14
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);
}
Esempio n. 15
0
static int32_t cacheex_add_to_cache_int(struct s_client *cl, ECM_REQUEST *er, int8_t csp)
{
    if(er->rc >= E_NOTFOUND) {
        return 0;
    }

    if(!cl)
    {
        return 0;
    }
    if(!csp && cl->reader && cl->reader->cacheex.mode != 2)  //from reader
    {
        cs_debug_mask(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
        return 0;
    }
    if(!csp && !cl->reader && cl->account && cl->account->cacheex.mode != 3)  //from user
    {
        cs_debug_mask(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
        return 0;
    }
    if(!csp && !cl->reader && !cl->account)    //not active!
    {
        cs_debug_mask(D_CACHEEX, "CACHEX received, but invalid client state %s", username(cl));
        return 0;
    }

    uint8_t i, c;
    uint8_t null = 0;
    for(i = 0; i < 16; i += 4)
    {
        c = ((er->cw[i] + er->cw[i + 1] + er->cw[i + 2]) & 0xff);
        null |= (er->cw[i] | er->cw[i + 1] | er->cw[i + 2]);
        if(er->cw[i + 3] != c)
        {
            cs_ddump_mask(D_CACHEEX, er->cw, 16, "push received cw with chksum error from %s", csp ? "csp" : username(cl));
            cl->cwcacheexerr++;
            if(cl->account)
            {
                cl->account->cwcacheexerr++;
            }
            return 0;
        }
    }

    if(null == 0 || chk_is_null_CW(er->cw))
    {
        cs_ddump_mask(D_CACHEEX, er->cw, 16, "push received null cw from %s", csp ? "csp" : username(cl));
        cl->cwcacheexerr++;
        if(cl->account)
        {
            cl->account->cwcacheexerr++;
        }
        return 0;
    }

    er->grp |= cl->grp;  //ok for mode2 reader too: cl->reader->grp
    er->rc = E_CACHEEX;
    er->cacheex_src = cl;
    er->selected_reader = cl->reader;
    er->client = NULL; //No Owner! So no fallback!

    if(check_client(cl))
    {
        cl->cwcacheexgot++;
        if(cl->account)
        {
            cl->account->cwcacheexgot++;
        }
        first_client->cwcacheexgot++;
    }

    add_hitcache(cl, er);  //we have to call it before add_cache, because in chk_process we could remove it!
    add_cache(er);
    cacheex_add_stats(cl, er->caid, er->srvid, er->prid, 1);

    cs_writelock(&ecm_pushed_deleted_lock);
    er->next = ecm_pushed_deleted;
    ecm_pushed_deleted = er;
    cs_writeunlock(&ecm_pushed_deleted_lock);

    return 1;  //NO free, we have to wait cache push out stuff ends.
}
Esempio n. 16
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
		{
Esempio n. 17
0
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;
}
Esempio n. 18
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] %s: start extracting nanos", __func__);
			//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] %s: %s emm-s", __func__, (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] %s: emm-gh", __func__);
			cs_ddump_mask(D_DVBAPI, buffer, pos, "[viaccess] %s: assembled emm", __func__);

			*len=pos;
			break;
	}
	return 1;
}
Esempio n. 19
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;
}
Esempio n. 20
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");
}
Esempio n. 21
0
void *work_thread(void *ptr)
{
	struct job_data *data = (struct job_data *)ptr;
	struct s_client *cl = data->cl;
	struct s_reader *reader = cl->reader;
	struct timeb start, end;  // start time poll, end time poll

	struct job_data tmp_data;
	struct pollfd pfd[1];

	pthread_setspecific(getclient, cl);
	cl->thread = pthread_self();
	cl->thread_active = 1;

	set_work_thread_name(data);

	struct s_module *module = get_module(cl);
	uint16_t bufsize = module->bufsize; //CCCam needs more than 1024bytes!
	if(!bufsize)
		{ bufsize = 1024; }

	uint8_t *mbuf;
	if(!cs_malloc(&mbuf, bufsize))
		{ return NULL; }
	cl->work_mbuf = mbuf; // Track locally allocated data, because some callback may call cs_exit/cs_disconect_client/pthread_exit and then mbuf would be leaked
	int32_t n = 0, rc = 0, i, idx, s;
	uint8_t dcw[16];
	int8_t restart_reader = 0;
	while(cl->thread_active)
	{
		cs_ftime(&start); // register start time
		while(cl->thread_active)
		{
			if(!cl || cl->kill || !is_valid_client(cl))
			{
				pthread_mutex_lock(&cl->thread_lock);
				cl->thread_active = 0;
				pthread_mutex_unlock(&cl->thread_lock);
				cs_debug_mask(D_TRACE, "ending thread (kill)");
				__free_job_data(cl, data);
				cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf)
				free_client(cl);
				if(restart_reader)
					{ restart_cardreader(reader, 0); }
				NULLFREE(mbuf);
				pthread_exit(NULL);
				return NULL;
			}

			if(data && data->action != ACTION_READER_CHECK_HEALTH)
				{ cs_debug_mask(D_TRACE, "data from add_job action=%d client %c %s", data->action, cl->typ, username(cl)); }

			if(!data)
			{
				if(!cl->kill && cl->typ != 'r')
					{ client_check_status(cl); } // do not call for physical readers as this might cause an endless job loop
				pthread_mutex_lock(&cl->thread_lock);
				if(cl->joblist && ll_count(cl->joblist) > 0)
				{
					LL_ITER itr = ll_iter_create(cl->joblist);
					data = ll_iter_next_remove(&itr);
					if(data)
						{ set_work_thread_name(data); }
					//cs_debug_mask(D_TRACE, "start next job from list action=%d", data->action);
				}
				pthread_mutex_unlock(&cl->thread_lock);
			}

			if(!data)
			{
				/* for serial client cl->pfd is file descriptor for serial port not socket
				   for example: pfd=open("/dev/ttyUSB0"); */
				if(!cl->pfd || module->listenertype == LIS_SERIAL)
					{ break; }
				pfd[0].fd = cl->pfd;
				pfd[0].events = POLLIN | POLLPRI;

				pthread_mutex_lock(&cl->thread_lock);
				cl->thread_active = 2;
				pthread_mutex_unlock(&cl->thread_lock);
				rc = poll(pfd, 1, 3000);
				pthread_mutex_lock(&cl->thread_lock);
				cl->thread_active = 1;
				pthread_mutex_unlock(&cl->thread_lock);
				if(rc > 0)
				{
					cs_ftime(&end); // register end time
					cs_debug_mask(D_TRACE, "[OSCAM-WORK] new event %d occurred on fd %d after %"PRId64" ms inactivity", pfd[0].revents,
								  pfd[0].fd, comp_timeb(&end, &start));
					data = &tmp_data;
					data->ptr = NULL;
					cs_ftime(&start); // register start time for new poll next run

					if(reader)
						{ data->action = ACTION_READER_REMOTE; }
					else
					{
						if(cl->is_udp)
						{
							data->action = ACTION_CLIENT_UDP;
							data->ptr = mbuf;
							data->len = bufsize;
						}
						else
							{ data->action = ACTION_CLIENT_TCP; }
						if(pfd[0].revents & (POLLHUP | POLLNVAL | POLLERR))
							{ cl->kill = 1; }
					}
				}
			}

			if(!data)
				{ continue; }

			if(!reader && data->action < ACTION_CLIENT_FIRST)
			{
				__free_job_data(cl, data);
				break;
			}

			if(!data->action)
				{ break; }

			struct timeb actualtime;
			cs_ftime(&actualtime);
			int32_t gone = comp_timeb(&actualtime, &data->time);
			if(data != &tmp_data && gone > (int) cfg.ctimeout+1000)
			{
				cs_debug_mask(D_TRACE, "dropping client data for %s time %dms", username(cl), gone);
				__free_job_data(cl, data);
				continue;
			}

			if(data != &tmp_data)
				{ cl->work_job_data = data; } // Track the current job_data
			switch(data->action)
			{
			case ACTION_READER_IDLE:
				reader_do_idle(reader);
				break;
			case ACTION_READER_REMOTE:
				s = check_fd_for_data(cl->pfd);
				if(s == 0)  // no data, another thread already read from fd?
					{ break; }
				if(s < 0)
				{
					if(reader->ph.type == MOD_CONN_TCP)
						{ network_tcp_connection_close(reader, "disconnect"); }
					break;
				}
				rc = reader->ph.recv(cl, mbuf, bufsize);
				if(rc < 0)
				{
					if(reader->ph.type == MOD_CONN_TCP)
						{ network_tcp_connection_close(reader, "disconnect on receive"); }
					break;
				}
				cl->last = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER ****************
				idx = reader->ph.c_recv_chk(cl, dcw, &rc, mbuf, rc);
				if(idx < 0) { break; }  // no dcw received
				if(!idx) { idx = cl->last_idx; }
				reader->last_g = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER **************** // for reconnect timeout
				for(i = 0, n = 0; i < cfg.max_pending && n == 0; i++)
				{
					if(cl->ecmtask[i].idx == idx)
					{
						cl->pending--;
						casc_check_dcw(reader, i, rc, dcw);
						n++;
					}
				}
				break;
			case ACTION_READER_RESET:
				cardreader_do_reset(reader);
				break;
			case ACTION_READER_ECM_REQUEST:
				reader_get_ecm(reader, data->ptr);
				break;
			case ACTION_READER_EMM:
				reader_do_emm(reader, data->ptr);
				break;
			case ACTION_READER_CARDINFO:
				reader_do_card_info(reader);
				break;
			case ACTION_READER_INIT:
				if(!cl->init_done)
					{ reader_init(reader); }
				break;
			case ACTION_READER_RESTART:
				cl->kill = 1;
				restart_reader = 1;
				break;
			case ACTION_READER_RESET_FAST:
				reader->card_status = CARD_NEED_INIT;
				cardreader_do_reset(reader);
				break;
			case ACTION_READER_CHECK_HEALTH:
				cardreader_do_checkhealth(reader);
				break;
			case ACTION_READER_CAPMT_NOTIFY:
				if(reader->ph.c_capmt) { reader->ph.c_capmt(cl, data->ptr); }
				break;
			case ACTION_CLIENT_UDP:
				n = module->recv(cl, data->ptr, data->len);
				if(n < 0) { break; }
				module->s_handler(cl, data->ptr, n);
				break;
			case ACTION_CLIENT_TCP:
				s = check_fd_for_data(cl->pfd);
				if(s == 0)  // no data, another thread already read from fd?
					{ break; }
				if(s < 0)    // system error or fd wants to be closed
				{
					cl->kill = 1; // kill client on next run
					continue;
				}
				n = module->recv(cl, mbuf, bufsize);
				if(n < 0)
				{
					cl->kill = 1; // kill client on next run
					continue;
				}
				module->s_handler(cl, mbuf, n);
				break;
			case ACTION_CACHEEX_TIMEOUT:
#ifdef CS_CACHEEX
				cacheex_timeout(data->ptr);
#endif
				break;
			case ACTION_FALLBACK_TIMEOUT:
				fallback_timeout(data->ptr);
				break;
			case ACTION_CLIENT_TIMEOUT:
				ecm_timeout(data->ptr);
				break;
			case ACTION_ECM_ANSWER_READER:
				chk_dcw(data->ptr);
				break;
			case ACTION_ECM_ANSWER_CACHE:
				write_ecm_answer_fromcache(data->ptr);
				break;
			case ACTION_CLIENT_INIT:
				if(module->s_init)
					{ module->s_init(cl); }
				cl->is_udp = module->type == MOD_CONN_UDP;
				cl->init_done = 1;
				break;
			case ACTION_CLIENT_IDLE:
				if(module->s_idle)
					{ module->s_idle(cl); }
				else
				{
					cs_log("user %s reached %d sec idle limit.", username(cl), cfg.cmaxidle);
					cl->kill = 1;
				}
				break;
			case ACTION_CACHE_PUSH_OUT:
			{
#ifdef CS_CACHEEX
				ECM_REQUEST *er = data->ptr;
				int32_t res = 0, stats = -1;
				// cc-nodeid-list-check
				if(reader)
				{
					if(reader->ph.c_cache_push_chk && !reader->ph.c_cache_push_chk(cl, er))
						{ break; }
					res = reader->ph.c_cache_push(cl, er);
					stats = cacheex_add_stats(cl, er->caid, er->srvid, er->prid, 0);
				}
				else
				{
					if(module->c_cache_push_chk && !module->c_cache_push_chk(cl, er))
						{ break; }
					res = module->c_cache_push(cl, er);
				}
				debug_ecm(D_CACHEEX, "pushed ECM %s to %s res %d stats %d", buf, username(cl), res, stats);
				cl->cwcacheexpush++;
				if(cl->account)
					{ cl->account->cwcacheexpush++; }
				first_client->cwcacheexpush++;
#endif
				break;
			}
			case ACTION_CLIENT_KILL:
				cl->kill = 1;
				break;
			case ACTION_CLIENT_SEND_MSG:
			{
#ifdef MODULE_CCCAM
				struct s_clientmsg *clientmsg = (struct s_clientmsg *)data->ptr;
				cc_cmd_send(cl, clientmsg->msg, clientmsg->len, clientmsg->cmd);
#endif
				break;
			}
			} // switch

			__free_job_data(cl, data);
		}

		if(thread_pipe[1] && (mbuf[0] != 0x00))
		{
			cs_ddump_mask(D_TRACE, mbuf, 1, "[OSCAM-WORK] Write to pipe:");
			if(write(thread_pipe[1], mbuf, 1) == -1)    // wakeup client check
			{
				cs_debug_mask(D_TRACE, "[OSCAM-WORK] Writing to pipe failed (errno=%d %s)", errno, strerror(errno));
			}
		}

		// Check for some race condition where while we ended, another thread added a job
		pthread_mutex_lock(&cl->thread_lock);
		if(cl->joblist && ll_count(cl->joblist) > 0)
		{
			pthread_mutex_unlock(&cl->thread_lock);
			continue;
		}
		else
		{
			cl->thread_active = 0;
			pthread_mutex_unlock(&cl->thread_lock);
			break;
		}
	}
	cl->thread_active = 0;
	cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf)
	NULLFREE(mbuf);
	pthread_exit(NULL);
	return NULL;
}
Esempio n. 22
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;
}
Esempio n. 23
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)
			call (Cool_Transmit(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;
}
Esempio n. 24
0
void do_emm(struct s_client * client, EMM_PACKET *ep)
{
	char *typtext[]={"unknown", "unique", "shared", "global"};
	char tmp[17];
	int32_t emmnok=0;

	struct s_reader *aureader = NULL;
	cs_ddump_mask(D_EMM, ep->emm, ep->emmlen, "emm:");

	int8_t cl_dvbapi = 0, assemble = 0;
#ifdef HAVE_DVBAPI
	cl_dvbapi = streq(cfg.dvbapi_usr, client->account->usr);
#endif
	if (client->account->emm_reassembly > 1 || (client->account->emm_reassembly && cl_dvbapi))
		assemble = 1;

	LL_ITER itr = ll_iter_create(client->aureader_list);
	while ((aureader = ll_iter_next(&itr))) {
		if (!aureader->enable)
			continue;

		uint16_t caid = b2i(2, ep->caid);
		uint32_t provid = b2i(4, ep->provid);

		if (aureader->audisabled) {
			rdr_debug_mask(aureader, D_EMM, "AU is disabled");
			/* we have to write the log for blocked EMM here because
			 this EMM never reach the reader module where the rest
			 of EMM log is done. */
			if (aureader->logemm & 0x10)  {
				rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=1: audisabled (0 ms)",
						client->account->usr,
						typtext[ep->type],
						ep->emm[2]);
			}
			continue;
		}

		if (!(aureader->grp & client->grp)) {
			rdr_debug_mask(aureader, D_EMM, "skip emm, group mismatch");
			continue;
		}

		//TODO: provider possibly not set yet, this is done in get_emm_type()
		if (!emm_reader_match(aureader, caid, provid))
			continue;

		struct s_cardsystem *cs = NULL;

		if (is_cascading_reader(aureader)) { // network reader (R_CAMD35 R_NEWCAMD R_CS378X R_CCCAM)
			if (!aureader->ph.c_send_emm) // no emm support
				continue;

			cs = get_cardsystem_by_caid(caid);
			if (!cs) {
				rdr_debug_mask(aureader, D_EMM, "unable to find cardsystem for caid %04X", caid);
				continue;
			}
		} else { // local reader
			if (aureader->csystem.active)
				cs=&aureader->csystem;
		}

		if (cs && cs->get_emm_type) {
			if (!cs->get_emm_type(ep, aureader)) {
				rdr_debug_mask(aureader, D_EMM, "emm skipped, get_emm_type() returns error");
				emmnok++;
				continue;
			}
		}

		if (cs && cs->get_emm_filter) {
			if (!do_simple_emm_filter(aureader, cs, ep)) {
				rdr_debug_mask(aureader, D_EMM, "emm skipped, emm_filter() returns invalid");
				emmnok++;
				continue;
			}
		}

		if (cs && cs->do_emm_reassembly) {
			if (assemble) {
				if (!cs->do_emm_reassembly(client, ep))
					return;
			} else {
				rdr_debug_mask(aureader, D_EMM, "processing raw emm");
			}
		}

		rdr_debug_mask_sensitive(aureader, D_EMM, "emmtype %s. Reader serial {%s}.", typtext[ep->type],
			cs_hexdump(0, aureader->hexserial, 8, tmp, sizeof(tmp)));
		rdr_debug_mask_sensitive(aureader, D_EMM, "emm UA/SA: {%s}.",
			cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp)));

		client->last = time(NULL);
		saveemm(aureader, ep);

		int32_t is_blocked = 0;
		switch (ep->type) {
			case UNKNOWN: is_blocked = (aureader->blockemm & EMM_UNKNOWN) == EMM_UNKNOWN; break;
			case UNIQUE : is_blocked = (aureader->blockemm & EMM_UNIQUE ) == EMM_UNIQUE;  break;
			case SHARED : is_blocked = (aureader->blockemm & EMM_SHARED ) == EMM_SHARED;  break;
			case GLOBAL : is_blocked = (aureader->blockemm & EMM_GLOBAL ) == EMM_GLOBAL;  break;
		}

		// if not already blocked we check for block by len
		if (!is_blocked) is_blocked = cs_emmlen_is_blocked( aureader, ep->emm[2] ) ;

		if (is_blocked != 0) {
#ifdef WEBIF
			aureader->emmblocked[ep->type]++;
			is_blocked = aureader->emmblocked[ep->type];
#endif
			/* we have to write the log for blocked EMM here because
			 this EMM never reach the reader module where the rest
			 of EMM log is done. */
			if (aureader->logemm & 0x08)  {
				rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=%d: blocked (0 ms)",
						client->account->usr,
						typtext[ep->type],
						ep->emm[2],
						is_blocked);
			}
			continue;
		}

		client->lastemm = time((time_t*)0);

		client->emmok++;
		if (client->account)
			client->account->emmok++;
		first_client->emmok++;

		//Check emmcache early:
		int32_t i;
		unsigned char md5tmp[CS_EMMSTORESIZE];
		struct s_client *au_cl = aureader->client;

		MD5(ep->emm, ep->emm[2], md5tmp);
		ep->client = client;

		for (i=0; i<CS_EMMCACHESIZE; i++) {
			if (!memcmp(au_cl->emmcache[i].emmd5, md5tmp, CS_EMMSTORESIZE)) {
				rdr_debug_mask(aureader, D_EMM, "emm found in cache: count %d rewrite %d",
					au_cl->emmcache[i].count, aureader->rewritemm);
				if (aureader->cachemm && (au_cl->emmcache[i].count > aureader->rewritemm)) {
					reader_log_emm(aureader, ep, i, 2, NULL);
					return;
				}
				break;
			}
		}

		EMM_PACKET *emm_pack;
		if (cs_malloc(&emm_pack, sizeof(EMM_PACKET))) {
			rdr_debug_mask(aureader, D_EMM, "emm is being sent to reader");
			memcpy(emm_pack, ep, sizeof(EMM_PACKET));
			add_job(aureader->client, ACTION_READER_EMM, emm_pack, sizeof(EMM_PACKET));
		}
	}
	if (emmnok > 0 && emmnok == ll_count(client->aureader_list)) {
		client->emmnok++;
		if (client->account)
			client->account->emmnok++;
		first_client->emmnok++;
	}
}
Esempio n. 25
0
static int32_t dre_do_emm (struct s_reader * reader, EMM_PACKET * ep)
{
    def_resp;

    cs_ddump_mask(D_READER, ep->emm, ((ep->emm[1] & 0x0f) << 8) + ep->emm[2] + 3, "EMM:");

    if (reader->caid == 0x4ae1) {
        if(ep->type == UNIQUE && ep->emm[39] == 0x3d)
        {   /* For new package activation. */
            uchar emmcmd58[26];
            emmcmd58[0] = 0x58;
            memcpy(&emmcmd58[1], &ep->emm[40], 24);
            emmcmd58[25] = 0x15;
            if ((dre_cmd (emmcmd58)))
                if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
                    return ERROR;
        }
        else
        {
            uchar emmcmd52[0x3a];
            emmcmd52[0] = 0x52;
            int32_t i;
            for (i = 0; i < 2; i++) {
                memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
                // check for shared address
                if(ep->emm[3]!=reader->sa[0][0])
                    return OK; // ignore, wrong address
                emmcmd52[0x39] = reader->provider;
                if ((dre_cmd (emmcmd52)))
                    if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
                        return ERROR; //exit if response is not 90 00
            }
        }
    }
    else {
        uchar emmcmd42[] =
        {   0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
            0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
            0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
            0x91,
            0x56, 0x58, 0x11
        };
        int32_t i;
        switch (ep->type) {
        case UNIQUE:
            for (i = 0; i < 2; i++) {
                memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
                emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
                emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
                emmcmd42[51] = reader->provider;
                if ((dre_cmd (emmcmd42))) {
                    if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
                        return ERROR;		//exit if response is not 90 00
                }
            }
            break;
        case SHARED:
        default:
            memcpy (emmcmd42 + 1, ep->emm + 6, 48);
            emmcmd42[51] = reader->provider;
            //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
            emmcmd42[50] = 0x58;
            emmcmd42[49] = ep->emm[5];	//keynr
            /* response:
               59 05 A2 02 05 01 5B
               90 00 */
            if ((dre_cmd (emmcmd42))) {	//first emm request
                if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
                    return ERROR;		//exit if response is not 90 00

                memcpy (emmcmd42 + 1, ep->emm + 55, 7);	//TODO OR next two lines?
                /*memcpy (emmcmd42 + 1, ep->emm + 55, 7);  //FIXME either I cant count or my EMM log contains errors
                   memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
                emmcmd42[51] = reader->provider;
                //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
                emmcmd42[50] = 0x58;
                emmcmd42[49] = ep->emm[54];	//keynr
                if ((dre_cmd (emmcmd42))) {	//second emm request
                    if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
                        return ERROR;		//exit if response is not 90 00
                }
            }
        }
    }
    return OK;			//success
}