Пример #1
0
static int32_t camd35_recv(uchar *buf, int32_t rs)
{
	int32_t rc = 0, s, n=0, buflen=0, len=0;
	for (s=0; !rc; s++) {
		switch(s) {
			case 0:
				if (rs < 36) {
					rc = -1;
					goto out;
				}
				break;
			case 1:
				switch (camd35_auth_client(buf)) {
					case  0:        break;	// ok
					case  1: rc=-2; break;	// unknown user
				}
				memmove(buf, buf+4, rs-=4);
				break;
			case 2:
				aes_decrypt(&cl_aes_keys, buf, rs);
				if (rs!=boundary(4, rs))
					cs_log_debug("WARNING: packet size has wrong decryption boundary");

				n=(buf[0]==3) ? 0x34 : 0;

				//Fix for ECM request size > 255 (use ecm length field)
				if(buf[0]==0)
					buflen = (((buf[21]&0x0f)<< 8) | buf[22])+3;
				else
					buflen = buf[1];

				n = boundary(4, n+20+buflen);

				cs_log_debug("received %d bytes from client", rs);

				if (n<rs)
					cs_log_debug("ignoring %d bytes of garbage", rs-n);
				else
					if (n>rs) rc=-3;
				break;
			case 3:
				if (crc32(0L, buf+20, buflen)!=b2i(4, buf+4)) rc=-4;
				if (!rc) rc=n;
				break;
		}
	}

out:
	switch(rc) {
		case -2:	cs_log("unknown user");			break;
		case -3:	cs_log("incomplete request!");			break;
		case -4:	cs_log("checksum error (wrong password?)");	break;
	}

	return(rc);
}
Пример #2
0
static void camd35_process_emm(uchar *buf, int buflen)
{
	uint32_t keysAdded = 0;
	uint16_t emmlen = 0;
	
	if(!buf || buflen < 23)
		{ return; }
		
	emmlen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3;
	if(emmlen + 20 > buflen)
		{ return; }
		
	cs_log_debug("ProcessEMM CAID: %X", (buf[10] << 8) | buf[11]);
	cs_log_hexdump("ProcessEMM: ", buf+20, emmlen);
	
	if(ProcessEMM((buf[10] << 8) | buf[11],
      (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15],buf+20,&keysAdded)) {
	  cs_log_debug("EMM nok");
	}
	else {
	  cs_log_debug("EMM ok");
    }	
}
Пример #3
0
static int32_t camd35_send(uchar *buf, int32_t buflen)
{
	int32_t l, status;
	unsigned char rbuf[REQ_SIZE + 15 + 4], *sbuf = rbuf + 4;

	//Fix ECM len > 255
	if(buflen <= 0)
		{ buflen = ((buf[0] == 0) ? (((buf[21] & 0x0f) << 8) | buf[22]) + 3 : buf[1]); }
	l = 20 + (((buf[0] == 3) || (buf[0] == 4)) ? 0x34 : 0) + buflen;
	memcpy(rbuf, cl_ucrc, 4);
	memcpy(sbuf, buf, l);
	memset(sbuf + l, 0xff, 15); // set unused space to 0xff for newer camd3's
	i2b_buf(4, crc32(0, sbuf + 20, buflen), sbuf + 4);
	l = boundary(4, l);
	cs_log_debug("send %d bytes to client", l);
	aes_encrypt_idx(&cl_aes_keys, sbuf, l);

	status = sendto(cl_sockfd, rbuf, l + 4, 0, (struct sockaddr *)&cl_socket, sizeof(cl_socket));
	return status;
}
Пример #4
0
static int32_t camd35_recv(uchar *buf, int32_t rs)
{
	int32_t rc, s, n = 0, buflen = 0;
	for(rc = s = 0; !rc; s++)
	{
		switch(s)
		{
		case 0:
			if(rs < 36)
			{
				rc = -1;
				goto out;
			}
			break;
		case 1:
			switch(camd35_auth_client(buf))
			{
			case  0:
				break;  // ok
			case  1:
				rc = -2;
				break; // unknown user
			default:
				rc = -9;
				break; // error's from cs_auth()
			}
			memmove(buf, buf + 4, rs -= 4);
			break;
		case 2:
			aes_decrypt(&cl_aes_keys, buf, rs);
			if(rs != boundary(4, rs))
				cs_log_debug("WARNING: packet size has wrong decryption boundary");

			n = (buf[0] == 3) ? 0x34 : 0;

			//Fix for ECM request size > 255 (use ecm length field)
			if(buf[0] == 0)
				{ buflen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; }
			else if(buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f)  //cacheex-push
				{ buflen = buf[1] | (buf[2] << 8); }
			else
				{ buflen = buf[1]; }

			n = boundary(4, n + 20 + buflen);

			cs_log_debug("received %d bytes from client", rs);

			if(n < rs)
				cs_log_debug("ignoring %d bytes of garbage", rs - n);
			else if(n > rs) { rc = -3; }
			break;
		case 3:
			if(crc32(0, buf + 20, buflen) != b2i(4, buf + 4)) { 
				rc = -4;
				cs_log_hexdump("camd35 checksum failed for packet: ", buf, rs);
				cs_log_debug("checksum: %X", b2i(4, buf+4)); 
			}
			if(!rc) { rc = n; }
			break;
		}
	}

out:
	if((rs > 0) && ((rc == -1) || (rc == -2)))
	{
		cs_log_debug("received %d bytes from client (native)", rs);
	}
	switch(rc)
	{
	case -1:
		cs_log("packet is too small (received %d bytes, expected at least 36 bytes)", rs);
		break;
	case -2:
		cs_log("unknown user");
		break;
	case -3:
		cs_log("incomplete request !");
		break;
	case -4:
		cs_log("checksum error (wrong password ?)");
		break;
	}

	return (rc);
}
Пример #5
0
static void camd35_process_ecm(uchar *buf, int buflen)
{
	ECM_REQUEST er;
	uint16_t ecmlen = 0;
	
	if(!buf || buflen < 23)
		{ return; }
	
	ecmlen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3;
	if(ecmlen + 20 > buflen)
		{ return; }
	
	memset(&er, 0, sizeof(ECM_REQUEST));
    er.rc = E_UNHANDLED;
	er.ecmlen = ecmlen;
	er.srvid = b2i(2, buf + 8);
	er.caid = b2i(2, buf + 10);
	er.prid = b2i(4, buf + 12);
	
	cs_log_debug("ProcessECM CAID: %X", er.caid);
	cs_log_hexdump("ProcessECM: ", buf+20, ecmlen);
	
	if(ProcessECM(er.caid,buf+20,er.cw)) {
	  er.rc = E_NOTFOUND;
	  cs_log_debug("CW not found");
	}
	else {
	  er.rc = E_FOUND;
	  cs_log_hexdump("Found CW: ", er.cw, 16);
    }
    
	if((er.rc == E_NOTFOUND || (er.rc == E_INVALID)) && !suppresscmd08)
	{
		buf[0] = 0x08;
		buf[1] = 2;
		memset(buf + 20, 0, buf[1]);
		buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3
	}
	else if(er.rc == E_STOPPED)
	{
		buf[0] = 0x08;
		buf[1] = 2;
		buf[20] = 0;
		/*
		 * the second Databyte should be forseen for a sleeptime in minutes
		 * whoever knows the camd3 protocol related to CMD08 - please help!
		 * on tests this don't work with native camd3
		 */
		buf[21] = 0;
		cs_log("client stop request send");
	}
	else
	{
		// Send CW
		if((er.rc < E_NOTFOUND) || (er.rc == E_FAKE))
		{
			if(buf[0] == 3)
				{ memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34); }
			buf[0]++;
			buf[1] = 16;
			memcpy(buf + 20, er.cw, buf[1]);
		}
		else
		{
			// Send old CMD44 to prevent cascading problems with older mpcs/oscam versions
			buf[0] = 0x44;
			buf[1] = 0;
		}
	}
	camd35_send(buf, 0);
}