static int pandora_recv(struct s_client *cl, uchar *buf, int32_t l) { int ret; if (!cl->udp_fd) return (-9); if (cl->typ != 'c') ret = recv_from_udpipe(buf); else { ret = recvfrom(cl->udp_fd, buf, l, 0, (struct sockaddr *)&cl->udp_sa, &cl->udp_sa_len); } if (ret < 1) return (-1); simple_crypt(buf, ret, cl->pand_md5_key, 16); cl->last = time((time_t *) 0); if (cl->typ != 'c') pandora_process_request(cl, buf, ret); return (ret); }
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); }
static int32_t monitor_recv(struct s_client * client, uchar *buf, int32_t l) { int32_t n; uchar nbuf[3] = { 'U', 0, 0 }; static int32_t bpos=0, res = 0; static uchar *bbuf=NULL; if (!bbuf) { if (!cs_malloc(&bbuf, l)) return 0; } if (bpos) memcpy(buf, bbuf, n=bpos); else n=recv_from_udpipe(buf); bpos=0; if (!n) return buf[0]=0; if (buf[0]=='&') { int32_t bsize; if (n<21) // 5+16 is minimum { cs_log("packet too small!"); return buf[0]=0; } res = secmon_auth_client(buf+1); if (res == -1) { cs_disconnect_client(client); return 0; } if (!res) return buf[0]=0; aes_decrypt(client, buf+5, 16); bsize=boundary(4, buf[9]+5)+5; // cs_log("n=%d bsize=%d", n, bsize); if (n>bsize) { // cs_log("DO >>>> copy-back"); memcpy(bbuf, buf+bsize, bpos=n-bsize); n=bsize; uchar *nbuf_cpy; if (cs_malloc(&nbuf_cpy, sizeof(nbuf))) { memcpy(nbuf_cpy, nbuf, sizeof(nbuf)); add_job(client, ACTION_CLIENT_UDP, &nbuf_cpy, sizeof(nbuf)); } } else if (n<bsize) { cs_log("packet-size mismatch !"); return buf[0]=0; } aes_decrypt(client, buf+21, n-21); uchar tmp[10]; if (memcmp(buf+5, i2b_buf(4, crc32(0L, buf+10, n-10), tmp), 4)) { cs_log("CRC error ! wrong password ?"); return buf[0]=0; } n=buf[9]; memmove(buf, buf+10, n); } else { uchar *p; if (monitor_check_ip() == -1) { cs_disconnect_client(client); return 0; } buf[n]='\0'; if ((p=(uchar *)strchr((char *)buf, 10)) && (bpos=n-(p-buf)-1)) { memcpy(bbuf, p+1, bpos); n=p-buf; uchar *nbuf_cpy; if (cs_malloc(&nbuf_cpy, sizeof(nbuf))) { memcpy(nbuf_cpy, nbuf, sizeof(nbuf)); add_job(client, ACTION_CLIENT_UDP, &nbuf_cpy, sizeof(nbuf)); } } } buf[n]='\0'; n=strlen(trim((char *)buf)); if (n) client->last=time((time_t *) 0); return n; }