- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / module-gbox-remm.c
blob21d4173201e397b8423d6dd48f4f1703b8ef4a0d
1 #define MODULE_LOG_PREFIX "gbox/remm"
3 #include "globals.h"
5 #ifdef MODULE_GBOX
6 #include "module-gbox-remm.h"
7 #include "module-gbox.h"
8 #include "module-gbox-helper.h"
9 #include "oscam-string.h"
10 #include "oscam-client.h"
11 #include "oscam-lock.h"
12 #include "oscam-time.h"
13 #include "oscam-reader.h"
14 #include "oscam-files.h"
15 #include "module-dvbapi.h"
16 #include "oscam-emm.h"
18 static void gbox_send_remm_ack_msg(struct s_client *cli, uint16_t caid, uint32_t provider, uint8_t dvbapi_stat, uint8_t ack)
20 uint8_t outbuf[32];
21 struct gbox_peer *peer = cli->gbox;
22 uint16_t local_gbox_id = gbox_get_local_gbox_id();
23 uint32_t local_gbox_pw = gbox_get_local_gbox_password();
25 gbox_message_header(outbuf, MSG_REM_EMM, peer->gbox.password, local_gbox_pw);
26 outbuf[10] = MSGID_REMM_ACK;
27 i2b_buf(2, peer->gbox.id, outbuf +11);
28 i2b_buf(2, local_gbox_id, outbuf + 13);
29 outbuf[15] = ack;
30 outbuf[16] = dvbapi_stat;
31 i2b_buf(2, caid, outbuf +17);
32 i2b_buf(4, provider, outbuf +19);
33 outbuf[23] = 0;
34 outbuf[24] = 0;
35 outbuf[25] = 0;
36 outbuf[26] = 0;
38 gbox_send(cli, outbuf, 27);
40 if (ack == PEER_AU_BLOCKED)
41 { cs_log("<- send REJECT REMM msg to peer %04X for caid: %04X", peer->gbox.id, caid); }
43 if (ack == PEER_AU_READY)
44 { cs_log("<- send ACCEPT REMM msg to peer %04X for caid: %04X", peer->gbox.id, caid); }
46 if (ack == PEER_AU_UNREADY)
47 { cs_log("<- send WARNING to peer %04X: my dvbapi unready for AU caid: %04X", peer->gbox.id, caid); }
49 return;
52 static void gbox_recvd_remm_ack_msg(struct s_client *cli, uint8_t *buf, int32_t n)
54 if (!cli || !cli->gbox || !buf || n != 27) { return; }
55 struct gbox_peer *peer;
56 peer = cli->gbox;
58 uint8_t ack = buf[15];
59 uint8_t dvbapi_stat = buf[16];
60 uint16_t rpeer = b2i(2, buf +11);
61 uint16_t rcaid = b2i(2, buf +17);
62 //uint32_t rprovid = b2i(4, buf +19);
64 if (ack == PEER_AU_BLOCKED)
65 { cs_log("-> Peer %04X %s rejected REMM for caid %04X - requesting peer %04X blocked", peer->gbox.id, cli->reader->label, rcaid, rpeer ); }
67 if (ack == PEER_AU_READY)
68 { cs_log("-> MSG from peer %04X %s: Accept REMM REQ for caid %04X", peer->gbox.id, cli->reader->label, rcaid); }
70 if (ack == PEER_AU_UNREADY)
72 cs_log("-> WARNING: Peer %04X %s dvbapi AU unready for caid %04X", peer->gbox.id, cli->reader->label, rcaid);
73 cs_log_dbg(D_EMM,"Peer %04X dvbapi AU status: dvbapi_au: %1d - dvbapi_usr_autoau: %1d - dvbapi_usr_aulist: %1d",
74 peer->gbox.id, (dvbapi_stat & 1) ? 1 : 0, (dvbapi_stat & 2) ? 1 : 0, (dvbapi_stat & 4) ? 1 : 0 );
78 static uint8_t check_dvbapi_au_ready( void)
80 #ifdef HAVE_DVBAPI
81 uint8_t dvbapi_stat = 0;
82 if (module_dvbapi_enabled())
84 if(cfg.dvbapi_au)
85 { dvbapi_stat |= 1; }
87 struct s_client *cl;
88 cs_readlock(__func__, &clientlist_lock);
90 for(cl = first_client; cl; cl = cl->next)
92 if(cl->typ == 'c' && cl->account && is_dvbapi_usr(cl->account->usr))
94 if(cl->account->autoau)
96 dvbapi_stat |= 2;
97 break;
100 if(ll_count(cl->account->aureader_list))
102 dvbapi_stat |= 4;
103 break;
107 cs_readunlock(__func__, &clientlist_lock);
109 return dvbapi_stat;
110 #else
111 return 0;
112 #endif
115 uint8_t check_valid_remm_peer(uint16_t peer_id)
117 if (cfg.accept_remm_peer_num > 0)
119 int i;
120 for (i = 0; i < cfg.accept_remm_peer_num; i++)
122 if (cfg.accept_remm_peer[i] == peer_id)
123 { return 1; }
126 return 0;
129 static void gbox_recvd_remm_req(struct s_client *cli, uint8_t *buf, int32_t n)
131 if (!cli || !cli->gbox || !buf || !cli->reader || n != 122) { return; }
133 struct gbox_peer *peer;
134 peer = cli->gbox;
136 uint16_t rcaid = b2i(2, buf +23);
137 uint32_t rprovid = b2i(4, buf +17);
138 //uint16_t tcli_peer = b2i(2, buf +11);
139 //uint16_t tsrv_peer = b2i(2, buf +13);
141 uint8_t dvbapi_stat = check_dvbapi_au_ready();
143 if (!check_valid_remm_peer( peer->gbox.id))
145 gbox_send_remm_ack_msg(cli, rcaid, rprovid, dvbapi_stat, PEER_AU_BLOCKED);
146 handle_attack(cli, GBOX_ATTACK_REMM_REQ_BLOCKED, peer->gbox.id);
147 cs_log("Reject REMM REQ for caid %04X) - peer %04X blocked for AU", rcaid, peer->gbox.id);
148 return;
151 //if (tcli_peer != local_gbox.id)
152 // { forward remm req to target client peer}
154 struct s_reader *rdr = cli->reader;
155 rdr->gbox_remm_peer = peer->gbox.id;
156 rdr->last_g = time(NULL); // last receive is now
158 rdr->auprovid = rprovid;
159 rdr->caid = rcaid;
161 memcpy(rdr->hexserial, buf + 29, 6);
162 rdr->hexserial[6] = 0;
163 rdr->hexserial[7] = 0;
164 rdr->nprov = buf[37];
166 int32_t i;
167 for(i = 0; i < rdr->nprov; i++)
169 if(caid_is_betacrypt(rdr->caid) || caid_is_irdeto(rdr->caid))
171 rdr->prid[i][0] = buf[38 + (i * 5)];
172 memcpy(&rdr->prid[i][1], &buf[40 + (i * 5)], 3);
174 else
176 rdr->prid[i][2] = buf[38 + (i * 5)];
177 rdr->prid[i][3] = buf[39 + (i * 5)];
178 memcpy(&rdr->sa[i][0], &buf[40 + (i * 5)], 4);
182 rdr->blockemm = 0;
183 rdr->blockemm |= (buf[117] == 1) ? 0 : 0x80; // remm marker bit
184 rdr->blockemm |= (buf[118] == 1) ? 0 : EMM_GLOBAL;
185 rdr->blockemm |= (buf[119] == 1) ? 0 : EMM_SHARED;
186 rdr->blockemm |= (buf[120] == 1) ? 0 : EMM_UNIQUE;
187 rdr->blockemm |= (buf[121] == 1) ? 0 : EMM_UNKNOWN;
189 cs_log("-> received REMM REQ for type %s%s%s%s caid %04X from peer %04X:%s",
190 buf[120]==1 ? "UQ ":"", buf[119]==1 ? "SH ":"", buf[118]==1 ? "GL ":"", buf[121]==1 ? "UK":"",
191 rdr->caid, peer->gbox.id, rdr->label);
193 if (dvbapi_stat == 3 || dvbapi_stat == 5)
195 gbox_send_remm_ack_msg(cli, rdr->caid, rdr->auprovid, dvbapi_stat, PEER_AU_READY);
196 cs_log_dbg(D_EMM,"my dvbapi ready for AU: dvbapi_au: %1d - dvbapi_usr_autoau: %1d - dvbapi_usr_aulist: %1d",
197 (dvbapi_stat & 1) ? 1 : 0, (dvbapi_stat & 2) ? 1 : 0, (dvbapi_stat & 4) ? 1 : 0 );
199 else
201 gbox_send_remm_ack_msg(cli, rdr->caid, rdr->auprovid, dvbapi_stat, PEER_AU_UNREADY);
202 cs_log_dbg(D_EMM,"dvbapi status: dvbapi_au: %1d - dvbapi_usr_autoau: %1d - dvbapi_usr_aulist: %1d",
203 (dvbapi_stat & 1) ? 1 : 0, (dvbapi_stat & 2) ? 1 : 0, (dvbapi_stat & 4) ? 1 : 0 );
205 write_msg_info(cli, MSGID_REMM, 0, 1);
208 static void gbox_recvd_remm_data(struct s_client *cli, uint8_t *buf, int32_t buflen, int32_t emmlen)
210 if(!cli || !cli->gbox || !buf || buflen < 30 || emmlen +27 > buflen || emmlen < 3 || emmlen + 27 > MAX_EMM_SIZE)
211 { return; }
213 struct gbox_peer *peer;
214 peer = cli->gbox;
216 uint16_t rcaid = b2i(2, buf + 15);
217 uint32_t recvd_remm_crc = b2i(4, buf + 23);
218 uint32_t calc_remm_crc = gbox_get_checksum(&buf[0] +27, emmlen);
219 cs_log_dbg(D_EMM,"received remm from peer: %04X caid: %04X (remm_crc = %08X - calc_remm_crc = %08X)",
220 peer->gbox.id, rcaid, recvd_remm_crc, calc_remm_crc);
222 if(recvd_remm_crc == calc_remm_crc)
224 EMM_PACKET remm;
225 memset(&remm, 0, sizeof(remm));
226 remm.emmlen = emmlen;
227 memcpy(remm.caid, buf +15, 2);
228 memcpy(remm.provid, buf +17 , 4);
229 memcpy(remm.emm, buf +27, remm.emmlen);
230 do_emm(cur_client(), &remm);
232 else
234 cs_log_dbg(D_EMM,"reject received REMM from peer %04X caid: %04X - crc failed - %08X != %08X",
235 peer->gbox.id, rcaid, recvd_remm_crc, calc_remm_crc);
238 return;
241 void gbox_recvd_remm_cmd_switch(struct s_client *cli, uint8_t *buf, int32_t n)
243 if (!cli || !cli->gbox || !buf || n < 26) { return; }
245 struct gbox_peer *peer;
246 peer = cli->gbox;
247 uint8_t cmd_id = buf[10];
249 switch(cmd_id)
251 case MSGID_REMM_REQ:
252 cs_log_dbg(D_EMM,"-> Incoming REMM request (%d bytes) from %04X %s - %s",
253 n, peer->gbox.id, username(cli), cli->reader->device);
254 gbox_recvd_remm_req(cli, buf, n);
255 break;
257 case MSGID_REMM_DATA:
258 cs_log_dbg(D_EMM,"-> Incoming gbox remote EMM data (%d bytes total - %d bytes emm-len) from %04X %s - %s",
259 n, buf[21], peer->gbox.id, username(cli), cli->reader->device);
260 gbox_recvd_remm_data(cli, buf, n, buf[21]); // buf[21]) = emm length
261 break;
263 case MSGID_REMM_ACK:
264 cs_log_dbg(D_EMM,"-> Incoming REMM ACK (%d bytes) from %04X %s - %s",
265 n, peer->gbox.id, username(cli), cli->reader->device);
266 gbox_recvd_remm_ack_msg(cli, buf, n);
267 break;
269 default:
270 cs_log("received unknown remm cmd_id: %d %d bytes from %04X %s - %s",
271 cmd_id, n, peer->gbox.id, username(cli), cli->reader->device);
272 return;
276 void gbox_send_remm_req(struct s_client *cli, ECM_REQUEST *er)
278 if (!cli || !cli->gbox || !er) { return; }
279 int32_t i;
280 uint8_t mbuf[1024];
281 struct s_client *cl = cur_client();
282 struct gbox_peer *peer = cli->gbox;
283 struct s_reader *aureader = NULL, *rdr = NULL;
285 if(er->selected_reader && !er->selected_reader->audisabled && ll_contains(cl->aureader_list, er->selected_reader))
286 { aureader = er->selected_reader; }
288 if(!aureader && cl->aureader_list)
290 LL_ITER itr = ll_iter_create(cl->aureader_list);
291 while((rdr = ll_iter_next(&itr)))
293 if(emm_reader_match(rdr, er->caid, er->prid))
295 aureader = rdr;
296 break;
301 if(!aureader)
302 { return; }
304 uint16_t au_caid = aureader->caid;
306 if(!au_caid && caid_is_bulcrypt(er->caid)) // Bulcrypt has 2 caids and aureader->caid can't be used. Use ECM_REQUEST caid for AU.
307 { au_caid = er->caid; }
309 if(cl->lastcaid != er->caid)
310 { cl->disable_counter = 0; }
312 cl->lastcaid = er->caid;
313 cl->disable_counter++;
315 if (!cli->reader->gbox_force_remm && cl->disable_counter < 6) // delay 6 ecm
316 { return; }
318 if(!memcmp(cl->lastserial, aureader->hexserial, 8))
320 cl->disable_counter = 0;
321 return;
324 memcpy(cl->lastserial, aureader->hexserial, 8);
326 if(au_caid)
327 { cl->disable_counter = 0; }
328 else
329 { return; }
331 uint8_t total_ent = 0;
332 uint8_t active_ent = 0;
334 if(aureader->ll_entitlements) // check for active entitlements
336 time_t now = time((time_t *)0);
337 LL_ITER itr = ll_iter_create(aureader->ll_entitlements);
338 S_ENTITLEMENT *ent;
340 while((ent = ll_iter_next(&itr)))
342 total_ent++;
343 if((ent->end > now) && (ent->type != 7))
345 active_ent++;
348 //cs_log("AU card %s: Total entitlements: %d - active entitlements: %d", aureader->label, total_ent, active_ent);
351 if(total_ent && cli->reader->gbox_force_remm)
353 if(active_ent >= cli->reader->gbox_force_remm)
355 cs_log("WARNING: Card '%s' got %d active entitlements - consider to disable 'force_remm'", aureader->label, active_ent);
359 memset(mbuf, 0, sizeof(mbuf));
361 uint16_t local_gbox_id = gbox_get_local_gbox_id();
362 uint32_t local_gbox_pw = gbox_get_local_gbox_password();
364 gbox_message_header(mbuf, MSG_REM_EMM, peer->gbox.password, local_gbox_pw);
365 mbuf[10] = MSGID_REMM_REQ;
366 i2b_buf(2, peer->gbox.id, mbuf + 11);
367 i2b_buf(2, local_gbox_id, mbuf + 13);
368 i2b_buf(2, er->srvid, mbuf + 15);
370 // override emm provid with auprovid if set in server reader config
371 if(aureader->auprovid)
373 if(aureader->auprovid != er->prid)
374 { i2b_buf(4, aureader->auprovid, mbuf +17); }
375 else
376 { i2b_buf(4, er->prid, mbuf +17); }
378 else
380 i2b_buf(4, er->prid, mbuf +17);
383 i2b_buf(2, er->pid, mbuf +21);
384 i2b_buf(2, au_caid, mbuf +23);
386 memcpy(mbuf +29, aureader->hexserial, 6); // serial 6 bytes
387 mbuf[37] = aureader->nprov;
389 for(i = 0; i < aureader->nprov; i++)
391 if(caid_is_betacrypt(au_caid) || caid_is_irdeto(au_caid))
393 mbuf[38 + (i * 5)] = aureader->prid[i][0];
394 memcpy(&mbuf[40 + (i * 5)], &aureader->prid[i][1], 3);
396 else
398 mbuf[38 + (i * 5)] = aureader->prid[i][2];
399 mbuf[39 + (i * 5)] = aureader->prid[i][3];
400 memcpy(&mbuf[40 + (i * 5)], &aureader->sa[i][0], 4); // for conax we need at least 4 Bytes
402 if(i >= 15) { break; }
405 mbuf[117] = aureader->blockemm | 0x80; // set remm marker bit
407 if(au_caid == 0x0D96 || au_caid == 0x0D98 ) // these caids needs globals
408 { mbuf[118] = (aureader->blockemm & EMM_GLOBAL && !(aureader->saveemm & EMM_GLOBAL)) ? 0 : 1; }
409 else
410 { mbuf[118] = 0; }
412 mbuf[119] = (aureader->blockemm & EMM_SHARED && !(aureader->saveemm & EMM_SHARED)) ? 0 : 1;
413 mbuf[120] = (aureader->blockemm & EMM_UNIQUE && !(aureader->saveemm & EMM_UNIQUE)) ? 0 : 1;
414 mbuf[121] = (aureader->blockemm & EMM_UNKNOWN && !(aureader->saveemm & EMM_UNKNOWN)) ? 0 : 1;
416 cs_log("<- %04X sends REMM REQ for type = %s%s%s%s to %s peer-id=%04X for reader=%s, caid=%04X", local_gbox_id,
417 mbuf[120] == 1 ? "UQ " : "", mbuf[119] == 1 ? "SH " : "", mbuf[118] == 1 ? "GL " : "", mbuf[121] == 1 ? "UK" : "",
418 username(cur_client()), peer->gbox.id, aureader->label, au_caid );
420 cs_log_dump_dbg(D_EMM, mbuf, 122, "<- send remm request, (data_len=%d):", 122);
421 gbox_send(cli, mbuf, 122);
422 return;
425 int32_t gbox_send_remm_data(EMM_PACKET *ep)
427 struct s_client *cli = cur_client();
428 struct gbox_peer *peer = cli->gbox;
430 if(!cli->gbox || !cli->reader->tcp_connected || !ep || !cli->reader->gbox_remm_peer)
431 { return 0; }
433 uint32_t remm_crc = gbox_get_checksum(&ep->emm[0], ep->emmlen);
435 if(remm_crc == peer->last_remm_crc)
436 { return 0; }
438 peer->last_remm_crc = remm_crc;
440 uint8_t *buf;
442 if(!cs_malloc(&buf, ep->emmlen +27 +15))
443 { return -1; }
445 memset(buf, 0, 26);
446 memset(buf +27, 0xff, ep->emmlen + 15);
448 uint16_t local_gbox_id = gbox_get_local_gbox_id();
449 uint32_t local_gbox_pw = gbox_get_local_gbox_password();
451 gbox_message_header(buf, MSG_REM_EMM, peer->gbox.password, local_gbox_pw);
452 buf[10] = MSGID_REMM_DATA;
453 i2b_buf(2, peer->gbox.id, buf +11);
454 i2b_buf(2, local_gbox_id, buf +13);
455 memcpy(buf +15, ep->caid, 2);
456 memcpy(buf +17, ep->provid, 4);
457 buf[21] = ep->emmlen;
458 i2b_buf(4, remm_crc, buf +23);
459 memcpy(buf +27, ep->emm, ep->emmlen);
460 cs_log("<- send remm to: %s peer: %04X emmlength: %d crc: %08X",
461 username(cur_client()), peer->gbox.id, ep->emmlen, remm_crc);
462 cs_log_dump_dbg(D_EMM, buf, 27 + ep->emmlen, "<- gbox send emm, (data-len=%d):", 27 + ep->emmlen);
463 gbox_send(cli, buf, 27 + ep->emmlen);
465 NULLFREE(buf);
466 return 1;
468 #endif