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);
}
Beispiel #2
0
static int32_t camd35_recv(uint8_t *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_dbg(0, "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_dbg(0, "received %d bytes from client", rs);

			if(n < rs)
			{ cs_log_dbg(0, "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_dump_dbg(buf, rs, "camd35 checksum failed for packet: ");
				cs_log_dbg(0, "checksum: %X", b2i(4, buf+4));
			}
			if(!rc) { rc = n; }
			break;
		}
	}

out:
	if((rs > 0) && ((rc == -1) || (rc == -2)))
	{
		cs_log_dbg(0, "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);
}
Beispiel #3
0
static int32_t camd35_recv(struct s_client *client, uchar *buf, int32_t l)
{
	int32_t rc, s, rs, n = 0, buflen = 0, len = 0;
	for(rc = rs = s = 0; !rc; s++)
	{
		switch(s)
		{
		case 0:
			if(!client->udp_fd) { return (-9); }
			if(client->is_udp && client->typ == 'c')
			{
				rs = recv_from_udpipe(buf);
			}
			else
			{
				//read minimum packet size (4 byte ucrc + 32 byte data) to detect packet size (tcp only)

				//rs = cs_recv(client->udp_fd, buf, client->is_udp ? l : 36, 0);
				if(client->is_udp){
					while (1){
					rs = cs_recv(client->udp_fd, buf, l, 0);
						if (rs < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}else {break;}
					}
				}else{
					int32_t tot=36, readed=0;
					rs = 0;
					do
					{
						readed = cs_recv(client->udp_fd, buf+rs, tot, 0);
						if (readed < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}
						if (readed == 0){ // nothing to read left!
							rc = -5;
							break;
						}
						if (readed > 0){ // received something, add it!
							tot-=readed;
						rs+=readed;
						}
					}
					while(tot!=0);
				}

			}
			if(rs < 36)
			{	
				if(rc != -5)
					{ rc = -1; }
				goto out;
			}
			break;
		case 1:
			switch(camd35_auth_client(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(client->aes_keys, buf, rs);
			if(rs != boundary(4, rs))
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "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);
			if(!(client->is_udp && client->typ == 'c') && (rs < n) && ((n - 32) > 0))
			{

				//len = cs_recv(client->udp_fd, buf+32, n-32, 0); // read the rest of the packet
				int32_t tot=n-32, readed=0;
				len = 0;
				do{
					readed = cs_recv(client->udp_fd, buf+32+len, tot, 0); // read the rest of the packet
					if (readed < 0){
						if(errno == EINTR) { continue; }  // try again in case of interrupt
						if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
						cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
						break;
					}
					if (readed == 0){ // nothing to read left!
						break;
					}
					if (readed > 0){ // received something, add it!
					tot-=readed;
					len+=readed;
					}
				}
				while(tot!=0);


				if(len > 0)
				{
					rs += len;
					aes_decrypt(client->aes_keys, buf + 32, len);
				}
				if(len < 0)
				{
					rc = -1;
					goto out;
				}
			}

			cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
						  buf, rs, "received %d bytes from %s", rs, remote_txt());

			if(n < rs)
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "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:
	if((rs > 0) && ((rc == -1) || (rc == -2)))
	{
		cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER, buf, rs,
					  "received %d bytes from %s (native)", rs, remote_txt());
	}
	if(rc >= 0) { client->last = time(NULL); }  // last client action is now
	switch(rc)
	{
		//case 0:   break;
	case -1:
		cs_log("packet is too small (received %d bytes, expected %d bytes)", rs, l);
		break;
	case -2:
		if(cs_auth_client(client, 0, "unknown user"))
			{ cs_disconnect_client(client); }
		break;
	case -3:
		cs_log("incomplete request !");
		break;
	case -4:
		cs_log("checksum error (wrong password ?)");
		break;
	case -5:
		cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "connection closed");
		break;		
		//default:  cs_log_dbg(D_TRACE, "camd35_recv returns rc=%d", rc); break;
	}

	return (rc);
}