49 |
49 |
#define CWS_NETMSGSIZE 256
|
50 |
50 |
#define CWS_FIRSTCMDNO 0xe0
|
51 |
51 |
|
|
52 |
/**
|
|
53 |
* cards for which emm updates are handled
|
|
54 |
*/
|
|
55 |
typedef enum {
|
|
56 |
CARD_IRDETO,
|
|
57 |
CARD_CONAX,
|
|
58 |
CARD_UNKNOWN
|
|
59 |
} card_type_t;
|
|
60 |
|
52 |
61 |
typedef enum {
|
53 |
62 |
MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
|
54 |
63 |
MSG_CLIENT_2_SERVER_LOGIN_ACK,
|
... | ... | |
195 |
204 |
/* Emm forwarding */
|
196 |
205 |
int cwc_forward_emm;
|
197 |
206 |
|
|
207 |
/* Card type */
|
|
208 |
card_type_t cwc_card_type;
|
|
209 |
|
198 |
210 |
/* From configuration */
|
199 |
211 |
|
200 |
212 |
uint8_t cwc_confedkey[14];
|
... | ... | |
221 |
233 |
|
222 |
234 |
static void cwc_transport_destroy(th_descrambler_t *td);
|
223 |
235 |
extern char *cwc_krypt(const char *key, const char *salt);
|
224 |
|
|
|
236 |
static void cwc_detect_card_type(cwc_t *cwc);
|
|
237 |
void cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len);
|
|
238 |
void cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len);
|
225 |
239 |
|
226 |
240 |
/**
|
227 |
241 |
*
|
... | ... | |
516 |
530 |
cwc->cwc_ua[0], cwc->cwc_ua[1], cwc->cwc_ua[2], cwc->cwc_ua[3], cwc->cwc_ua[4], cwc->cwc_ua[5], cwc->cwc_ua[6], cwc->cwc_ua[7],
|
517 |
531 |
nprov);
|
518 |
532 |
|
|
533 |
cwc_detect_card_type(cwc);
|
|
534 |
|
519 |
535 |
msg += 15;
|
520 |
536 |
plen -= 12;
|
521 |
537 |
|
... | ... | |
557 |
573 |
if (!emm_allowed)
|
558 |
574 |
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (not allowed by server)",
|
559 |
575 |
cwc->cwc_hostname);
|
560 |
|
else if ((cwc->cwc_caid>>8) != 0x0b)
|
561 |
|
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (unsupported ca system)",
|
562 |
|
cwc->cwc_hostname);
|
563 |
|
else {
|
|
576 |
else if (cwc->cwc_card_type != CARD_UNKNOWN) {
|
564 |
577 |
tvhlog(LOG_INFO, "cwc", "%s: Will forward EMMs",
|
565 |
578 |
cwc->cwc_hostname);
|
566 |
579 |
cwc->cwc_forward_emm = 1;
|
567 |
|
}
|
|
580 |
} else
|
|
581 |
tvhlog(LOG_INFO, "cwc", "%s: Will not forward EMMs (unsupported ca system)",
|
|
582 |
cwc->cwc_hostname);
|
568 |
583 |
}
|
569 |
584 |
|
570 |
585 |
return 0;
|
571 |
586 |
}
|
572 |
587 |
|
|
588 |
/**
|
|
589 |
* Detects the cam card type
|
|
590 |
* If you want to add another card, have a look at
|
|
591 |
* http://www.dvbservices.com/identifiers/ca_system_id?page=3
|
|
592 |
*
|
|
593 |
* based on the equivalent in sasc-ng
|
|
594 |
*/
|
|
595 |
static void
|
|
596 |
cwc_detect_card_type(cwc_t *cwc)
|
|
597 |
{
|
|
598 |
uint8_t c_sys = cwc->cwc_caid >> 8;
|
|
599 |
|
|
600 |
switch (c_sys)
|
|
601 |
{
|
|
602 |
case 0x17:
|
|
603 |
case 0x06:
|
|
604 |
cwc->cwc_card_type = CARD_IRDETO;
|
|
605 |
tvhlog(LOG_INFO, "cwc", "%s: irdeto card",
|
|
606 |
cwc->cwc_hostname);
|
|
607 |
break;
|
|
608 |
case 0x0b:
|
|
609 |
cwc->cwc_card_type = CARD_CONAX;
|
|
610 |
tvhlog(LOG_INFO, "cwc", "%s: conax card",
|
|
611 |
cwc->cwc_hostname);
|
|
612 |
break;
|
|
613 |
default:
|
|
614 |
cwc->cwc_card_type = CARD_UNKNOWN;
|
|
615 |
tvhlog(LOG_INFO, "cwc", "%s: unknown card",
|
|
616 |
cwc->cwc_hostname);
|
|
617 |
}
|
|
618 |
}
|
573 |
619 |
|
574 |
620 |
/**
|
575 |
621 |
* Login command
|
... | ... | |
1037 |
1083 |
lock_assert(&global_lock);
|
1038 |
1084 |
|
1039 |
1085 |
TAILQ_FOREACH(cwc, &cwcs, cwc_link)
|
1040 |
|
if(cwc->cwc_forward_emm && cwc->cwc_writer_running &&
|
1041 |
|
data[0] == 0x82 /* Conax */ ) {
|
1042 |
|
int i;
|
1043 |
|
for (i=0; i < cwc->cwc_num_providers; i++)
|
1044 |
|
if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0) {
|
1045 |
|
cwc_send_msg(cwc, data, len, 0, 1);
|
1046 |
|
break;
|
1047 |
|
}
|
|
1086 |
if(cwc->cwc_forward_emm && cwc->cwc_writer_running)
|
|
1087 |
{
|
|
1088 |
switch (cwc->cwc_card_type)
|
|
1089 |
{
|
|
1090 |
case CARD_CONAX:
|
|
1091 |
cwc_emm_conax(cwc, data, len);
|
|
1092 |
break;
|
|
1093 |
case CARD_IRDETO:
|
|
1094 |
cwc_emm_irdeto(cwc, data, len);
|
|
1095 |
break;
|
|
1096 |
case CARD_UNKNOWN:
|
|
1097 |
break;
|
|
1098 |
}
|
|
1099 |
}
|
|
1100 |
}
|
|
1101 |
|
|
1102 |
|
|
1103 |
/**
|
|
1104 |
* conax emm handler
|
|
1105 |
*/
|
|
1106 |
void
|
|
1107 |
cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len)
|
|
1108 |
{
|
|
1109 |
if (data[0] == 0x82)
|
|
1110 |
{
|
|
1111 |
int i;
|
|
1112 |
for (i=0; i < cwc->cwc_num_providers; i++)
|
|
1113 |
{
|
|
1114 |
if (memcmp(&data[3], &cwc->cwc_providers[i].sa[1], 7) == 0)
|
|
1115 |
{
|
|
1116 |
cwc_send_msg(cwc, data, len, 0, 1);
|
|
1117 |
break;
|
|
1118 |
}
|
|
1119 |
}
|
|
1120 |
}
|
|
1121 |
}
|
|
1122 |
|
|
1123 |
|
|
1124 |
/**
|
|
1125 |
* irdeto emm handler
|
|
1126 |
* inspired by opensasc-ng, https://opensvn.csie.org/traccgi/opensascng/
|
|
1127 |
*/
|
|
1128 |
void
|
|
1129 |
cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len)
|
|
1130 |
{
|
|
1131 |
int emm_mode = data[3] >> 3;
|
|
1132 |
int emm_len = data[3] & 0x07;
|
|
1133 |
int match = 0;
|
|
1134 |
|
|
1135 |
if (emm_mode & 0x10)
|
|
1136 |
{
|
|
1137 |
// try to match card
|
|
1138 |
match = (emm_mode == cwc->cwc_ua[4] &&
|
|
1139 |
(!emm_len || // zero length
|
|
1140 |
!memcmp(&data[4], &cwc->cwc_ua[5], emm_len))); // exact match
|
|
1141 |
}
|
|
1142 |
else
|
|
1143 |
{
|
|
1144 |
// try to match provider
|
|
1145 |
int i;
|
|
1146 |
for(i=0; i < cwc->cwc_num_providers; i++)
|
|
1147 |
{
|
|
1148 |
match = (emm_mode == cwc->cwc_providers[i].sa[4] &&
|
|
1149 |
(!emm_len || // zero length
|
|
1150 |
!memcmp(&data[4], &cwc->cwc_providers[i].sa[5], emm_len))); // exact match
|
|
1151 |
|
|
1152 |
if (match) break;
|
1048 |
1153 |
}
|
|
1154 |
}
|
|
1155 |
|
|
1156 |
if (match)
|
|
1157 |
cwc_send_msg(cwc, data, len, 0, 1);
|
1049 |
1158 |
}
|
1050 |
1159 |
|
1051 |
1160 |
|